home *** CD-ROM | disk | FTP | other *** search
/ MPEG Toolkit / MPEG Toolkit.iso / dos / mpegstat / video.c < prev    next >
C/C++ Source or Header  |  1997-01-01  |  90KB  |  3,328 lines

  1. /* MPEGSTAT - analyzing tool for MPEG-I video streams
  2.  * 
  3.  * Technical University of Berlin, Germany, Dept. of Computer Science
  4.  * Tom Pfeifer - Multimedia systems project - pfeifer@fokus.gmd.de
  5.  *
  6.  * Jens Brettin, Harald Masche, Alexander Schulze, Dirk Schubert
  7.  *
  8.  * This program uses parts of the source code of the Berkeley MPEG player
  9.  *
  10.  * ---------------------------
  11.  *
  12.  * Copyright (c) 1993 Technical University of Berlin, Germany
  13.  *
  14.  * for the parts of the Berkeley player used:
  15.  *
  16.  * Copyright (c) 1992 The Regents of the University of California.
  17.  * All rights reserved.
  18.  *
  19.  * ---------------------------
  20.  *
  21.  * Permission to use, copy, modify, and distribute this software and its
  22.  * documentation for any purpose, without fee, and without written agreement is
  23.  * hereby granted, provided that the above copyright notices and the following
  24.  * two paragraphs appear in all copies of this software.
  25.  * 
  26.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA 
  27.  * or the Technical University of Berlin BE LIABLE TO ANY PARTY FOR
  28.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  29.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  30.  * CALIFORNIA or the Technical University of Berlin HAS BEEN ADVISED OF THE 
  31.  * POSSIBILITY OF SUCH DAMAGE.
  32.  * 
  33.  * THE UNIVERSITY OF CALIFORNIA and the Technical University of Berlin 
  34.  * SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
  35.  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  36.  * PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE 
  37.  * UNIVERSITY OF CALIFORNIA and the Technical University of Berlin HAVE NO 
  38.  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 
  39.  * OR MODIFICATIONS.
  40.  */
  41. /* This file contains C code that implements
  42.  * the video decoder model.
  43.  */
  44.  
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <assert.h>
  48.  
  49. #ifndef MIPS
  50. #include <sys/time.h>
  51. #else
  52. #include <sys/types.h>
  53. #include <sys/system.h>
  54. #endif
  55.  
  56. #include "decoders.h"
  57. #include "video.h"
  58. #include "util.h"
  59. #include "proto.h"
  60. #include "dither.h"
  61.  
  62. /* Declarations of functions. */
  63. static void ReconIMBlock();
  64. static void ReconPMBlock();
  65. static void ReconBMBlock();
  66. static void ReconBiMBlock();
  67. static void ReconSkippedBlock();
  68. static void DoPictureDisplay();
  69. static int ParseSeqHead();
  70. static int ParseGOP();
  71. static int ParsePicture();
  72. static int ParseSlice();
  73. static int ParseMacroBlock();
  74. static void ProcessSkippedPFrameMBlocks();
  75. static void ProcessSkippedBFrameMBlocks();
  76.  
  77. extern int ditherType;
  78. char *ditherFlags;
  79. int vidstream_no = 0;
  80.  
  81. /* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */
  82.  
  83. #define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1))
  84.  
  85. /* Declare global pointer to vid stream used for current decoding. */
  86.  
  87. VidStream *curVidStream = NULL;
  88.  
  89. /* Set up array for fast conversion from zig zag order to row/column
  90.    coordinates.
  91. */
  92.  
  93. int zigzag[64][2] = {
  94.   0, 0, 1, 0, 0, 1, 0, 2, 1, 1, 2, 0, 3, 0, 2, 1, 1, 2, 0, 3, 0, 4, 1, 3,
  95.   2, 2, 3, 1, 4, 0, 5, 0, 4, 1, 3, 2, 2, 3, 1, 4, 0, 5, 0, 6, 1, 5, 2, 4,
  96.   3, 3, 4, 2, 5, 1, 6, 0, 7, 0, 6, 1, 5, 2, 4, 3, 3, 4, 2, 5, 1, 6, 0, 7,
  97.   1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6, 2, 7, 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6,
  98.   2, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 5, 7, 6, 6,
  99. 7, 5, 7, 6, 6, 7, 7, 7};
  100. /* Array mapping zigzag to array pointer offset. */
  101.  
  102. int zigzag_direct[64] = {
  103.   0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12,
  104.   19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
  105.   42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
  106. 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
  107. /* Set up array for fast conversion from row/column coordinates to
  108.    zig zag order.
  109. */
  110.  
  111. int scan[8][8] = {
  112.   {0, 1, 5, 6, 14, 15, 27, 28},
  113.   {2, 4, 7, 13, 16, 26, 29, 42},
  114.   {3, 8, 12, 17, 25, 30, 41, 43},
  115.   {9, 11, 18, 24, 31, 40, 44, 53},
  116.   {10, 19, 23, 32, 39, 45, 52, 54},
  117.   {20, 22, 33, 38, 46, 51, 55, 60},
  118.   {21, 34, 37, 47, 50, 56, 59, 61},
  119. {35, 36, 48, 49, 57, 58, 62, 63}};
  120. /* Initialize P and B skip flags. */
  121.  
  122. static int No_P_Flag = 0;
  123. static int No_B_Flag = 0;
  124.  
  125. /* Max lum, chrom indices for illegal block checking. */
  126.  
  127. static int lmaxx;
  128. static int lmaxy;
  129. static int cmaxx;
  130. static int cmaxy;
  131.  
  132. /*
  133.  * We use a lookup table to make sure values stay in the 0..255 range.
  134.  * Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this
  135.  * table the "crop table".
  136.  * MAX_NEG_CROP is the maximum neg/pos value we can handle.
  137.  */
  138.  
  139. #define MAX_NEG_CROP 384
  140. #define NUM_CROP_ENTRIES (256+2*MAX_NEG_CROP)
  141. #define assertCrop(x)    assert(((x) >= -MAX_NEG_CROP) && \
  142.                    ((x) <= 256+MAX_NEG_CROP))
  143. static unsigned char cropTbl[NUM_CROP_ENTRIES];
  144.  
  145.  
  146.  
  147. unsigned int bitCount = 0;
  148.  
  149. int showmb_flag = 0;
  150. int showEachFlag = 0;
  151.  
  152. typedef struct {
  153.   int frametype;
  154.   unsigned int totsize;
  155.   unsigned int number;
  156.   unsigned int i_mbsize;
  157.   unsigned int p_mbsize;
  158.   unsigned int b_mbsize;
  159.   unsigned int bi_mbsize;
  160.   unsigned int i_mbnum;
  161.   unsigned int p_mbnum;
  162.   unsigned int b_mbnum;
  163.   unsigned int bi_mbnum;
  164.   unsigned int i_mbcbp[64];
  165.   unsigned int p_mbcbp[64];
  166.   unsigned int b_mbcbp[64];
  167.   unsigned int bi_mbcbp[64];
  168.   unsigned int i_mbcoeff[64];
  169.   unsigned int p_mbcoeff[64];
  170.   unsigned int b_mbcoeff[64];
  171.   unsigned int bi_mbcoeff[64];
  172.   double tottime;
  173. } Statval;
  174.  
  175. Statval stat_a[4];
  176. unsigned int pictureSizeCount;
  177. unsigned int mbSizeCount;
  178. unsigned int *mbCBPPtr, *mbCoeffPtr, *mbSizePtr;
  179. unsigned int cacheHit[8][8];
  180. unsigned int cacheMiss[8][8];
  181.  
  182. static void
  183. init_stat_struct(astat)
  184.   Statval *astat;
  185. {
  186.   int j;
  187.  
  188.   astat->frametype = 0;
  189.   astat->totsize = 0;
  190.   astat->number = 0;
  191.   astat->i_mbsize = 0;
  192.   astat->p_mbsize = 0;
  193.   astat->b_mbsize = 0;
  194.   astat->bi_mbsize = 0;
  195.   astat->i_mbnum = 0;
  196.   astat->p_mbnum = 0;
  197.   astat->b_mbnum = 0;
  198.   astat->bi_mbnum = 0;
  199.  
  200.   for (j = 0; j < 64; j++) {
  201.  
  202.     astat->i_mbcbp[j] = 0;
  203.     astat->p_mbcbp[j] = 0;
  204.     astat->b_mbcbp[j] = 0;
  205.     astat->bi_mbcbp[j] = 0;
  206.     astat->i_mbcoeff[j] = 0;
  207.     astat->p_mbcoeff[j] = 0;
  208.     astat->b_mbcoeff[j] = 0;
  209.     astat->bi_mbcoeff[j] = 0;
  210.   }
  211.   astat->tottime = 0.0;
  212. }
  213.  
  214. void
  215. init_stats()
  216. {
  217.   int i, j;
  218.  
  219.   for (i = 0; i < 4; i++) {
  220.     init_stat_struct(&(stat_a[i]));
  221.     stat_a[i].frametype = i;
  222.   }
  223.  
  224.   for (i = 0; i < 8; i++) {
  225.     for (j = 0; j < 8; j++) {
  226.       cacheHit[i][j] = 0;
  227.       cacheMiss[i][j] = 0;
  228.     }
  229.   }
  230.  
  231.   bitCount = 0;
  232. }
  233.  
  234. void
  235. PrintAllStats()
  236. {
  237.   int i, j;
  238.   int average, pixelnum;
  239.  
  240.   unsigned int supertot, supernum;
  241.   double supertime;
  242.  
  243.   ShowFrameSeq();
  244.  
  245.  
  246.   pixelnum = curVidStream->mb_width * 16 * curVidStream->mb_height * 16;
  247.  
  248.   printf("\nSUMMARY:\n\n");
  249.  
  250.   supertot = stat_a[1].totsize + stat_a[2].totsize + stat_a[3].totsize;
  251.   supernum = stat_a[1].number + stat_a[2].number + stat_a[3].number;
  252.   supertime = stat_a[1].tottime + stat_a[2].tottime + stat_a[3].tottime;
  253.  
  254.   printf("Total Bytes read: %d. Total number of frames: %d\n\n", print_bytes(),
  255.           supernum);
  256.  
  257.   printf("Width: %d\tHeight: %d\n", 
  258.         curVidStream->h_size,
  259.         curVidStream->v_size);
  260.  
  261.   printf("Avg. Frame Size: %d bytes + %d bits\n\n",
  262.      supertot / (8 * supernum), (supertot / supernum) % 8);
  263.  
  264.   printf ("Factor of quantization [scales quantization matrix]: %d\n", 
  265.       mvstat (0, 9));
  266.  
  267.   printf("Total Compression Rate: %5.2f %% of uncompressed 24 bit images\n", 
  268.         ((float)supertot/(8.0*(float)supernum))*100.0 / 
  269.                 ((float)pixelnum*3.0) );
  270.  
  271.   printf("                        = %5.2f bits per pixel\n\n", 
  272.         .24 * (((float)supertot/(8.0*(float)supernum))*100.0 / 
  273.                 ((float)pixelnum*3.0)) );
  274.  
  275.   printf("Number of Macroblocks");
  276.   printf(" [width * height = sum]: %d x %d = %d per frame\n\n", 
  277.          curVidStream->mb_width, curVidStream->mb_height,
  278.      curVidStream->mb_width * curVidStream->mb_height);
  279.  
  280.   printf("Total Time Decoding: %g secs.\n\n", supertime);
  281.   printf("Avg. Decoding Time/Frame: %g secs.\n", supertime / ((double) supernum));
  282.   printf("Avg. Decoding Frames/Sec: %g \n", ((double) supernum) / supertime);
  283.   printf("\n");
  284.   printf("MPEG-Viewer requirements:\n\n");
  285.   printf("Required display speed: %d frames / second\n", 
  286.             curVidStream->picture_rate);
  287.  
  288.   printf("Length of vectors in pixels:\n\n");
  289.  
  290.   printf ("\tHorizontal forward vectors, maximum : %3d\taverage: %3d\n", 
  291.       mvstat (0, 5), mvstat(0, 10));
  292.   printf ("\tVertical forward vectors, maximum   : %3d\taverage: %3d\n\n", 
  293.       mvstat (0, 6), mvstat(0, 11));
  294.   printf ("\tHorizontal backward vectors, maximum: %3d\taverage: %3d\n", 
  295.       mvstat (0, 7), mvstat(0, 12));
  296.   printf ("\tVertical backward vectors, maximum  : %3d\taverage: %3d\n", 
  297.       mvstat (0, 8), mvstat(0, 13));
  298.  
  299.  
  300.   printf("\n\nFrame specific information:\n\n");
  301.  
  302.   for (i = 1; i < 4; i++) {
  303.  
  304.     if (stat_a[i].number == 0)
  305.       continue;
  306.  
  307.     printf("%-3d %c FRAMES, average is:\n", stat_a[i].number, "IPB"[i-1]);
  308.  
  309.     average = stat_a[i].totsize / (8 * stat_a[i].number);
  310.     printf("\tSize: %d bytes + %d bits\n",
  311.        average, (stat_a[i].totsize / stat_a[i].number) % 8);
  312.  
  313.     printf("\tCompression Rate: %5.2f%%\n", 
  314.     (float)average*100.0/ ( (float) pixelnum*3.0));
  315.  
  316.     if (stat_a[i].bi_mbnum > 0) {
  317.       printf("\t%5.2f%% interpolated Macro Blocks\n", 
  318.     ((float) stat_a[i].bi_mbnum*100.0) / (stat_a[i].i_mbnum + 
  319.     stat_a[i].p_mbnum + stat_a[i].b_mbnum + stat_a[i].bi_mbnum));
  320.     }
  321.     printf("\tTime to Decode: %f secs.\n",
  322.        (stat_a[i].tottime / ((double) stat_a[i].number)));
  323.     printf("\n");
  324.   }
  325.  
  326. }
  327.  
  328. static void
  329. CollectStats()
  330. {
  331.   int i, j;
  332.  
  333.   i = stat_a[0].frametype;
  334.  
  335.   stat_a[i].totsize += stat_a[0].totsize;
  336.   stat_a[i].number += stat_a[0].number;
  337.   stat_a[i].i_mbsize += stat_a[0].i_mbsize;
  338.   stat_a[i].p_mbsize += stat_a[0].p_mbsize;
  339.   stat_a[i].b_mbsize += stat_a[0].b_mbsize;
  340.   stat_a[i].bi_mbsize += stat_a[0].bi_mbsize;
  341.   stat_a[i].i_mbnum += stat_a[0].i_mbnum;
  342.   stat_a[i].p_mbnum += stat_a[0].p_mbnum;
  343.   stat_a[i].b_mbnum += stat_a[0].b_mbnum;
  344.   stat_a[i].bi_mbnum += stat_a[0].bi_mbnum;
  345.  
  346.   for (j = 0; j < 64; j++) {
  347.  
  348.     stat_a[i].i_mbcbp[j] += stat_a[0].i_mbcbp[j];
  349.     stat_a[i].p_mbcbp[j] += stat_a[0].p_mbcbp[j];
  350.     stat_a[i].b_mbcbp[j] += stat_a[0].b_mbcbp[j];
  351.     stat_a[i].bi_mbcbp[j] += stat_a[0].bi_mbcbp[j];
  352.     stat_a[i].i_mbcoeff[j] += stat_a[0].i_mbcoeff[j];
  353.     stat_a[i].p_mbcoeff[j] += stat_a[0].p_mbcoeff[j];
  354.     stat_a[i].b_mbcoeff[j] += stat_a[0].b_mbcoeff[j];
  355.     stat_a[i].bi_mbcoeff[j] += stat_a[0].bi_mbcoeff[j];
  356.   }
  357.  
  358.   stat_a[i].tottime += stat_a[0].tottime;
  359.  
  360.   init_stat_struct(&(stat_a[0]));
  361. }
  362.  
  363. static unsigned int
  364. bitCountRead()
  365. {
  366.   return bitCount;
  367. }
  368.  
  369. static void
  370. StartTime()
  371. {
  372.   stat_a[0].tottime = ReadSysClock();
  373. }
  374.  
  375. static void
  376. EndTime()
  377. {
  378.   stat_a[0].tottime = ReadSysClock() - stat_a[0].tottime;
  379. }
  380.  
  381. double realTimeStart;
  382. int totNumFrames = 0;
  383.  
  384. double
  385. ReadSysClock()
  386. {
  387.   struct timeval tv;
  388.   (void) gettimeofday(&tv, (struct timezone *)NULL);
  389.   return (tv.tv_sec + tv.tv_usec / 1000000.0);
  390. }
  391.  
  392. void
  393. PrintTimeInfo()
  394. {
  395.   double spent;
  396.  
  397.   spent = ReadSysClock() - realTimeStart;
  398.  
  399. }
  400.  
  401.  
  402.  
  403. /*
  404.  *--------------------------------------------------------------
  405.  *
  406.  * NewVidStream --
  407.  *
  408.  *    Allocates and initializes a VidStream structure. Takes
  409.  *      as parameter requested size for buffer length.
  410.  *
  411.  * Results:
  412.  *    A pointer to the new VidStream structure.
  413.  *
  414.  * Side effects:
  415.  *      None.
  416.  *
  417.  *--------------------------------------------------------------
  418.  */
  419.  
  420. VidStream *
  421. NewVidStream(bufLength)
  422.   int bufLength;
  423. {
  424.   int i, j;
  425.   VidStream *new;
  426.   static unsigned char default_intra_matrix[64] = {
  427.     8, 16, 19, 22, 26, 27, 29, 34,
  428.     16, 16, 22, 24, 27, 29, 34, 37,
  429.     19, 22, 26, 27, 29, 34, 34, 38,
  430.     22, 22, 26, 27, 29, 34, 37, 40,
  431.     22, 26, 27, 29, 32, 35, 40, 48,
  432.     26, 27, 29, 32, 35, 40, 48, 58,
  433.     26, 27, 29, 34, 38, 46, 56, 69,
  434.   27, 29, 35, 38, 46, 56, 69, 83};
  435.  
  436.   vidstream_no++;
  437.  
  438.   /* Check for legal buffer length. */
  439.  
  440.   if (bufLength < 4)
  441.     return NULL;
  442.  
  443.   /* Make buffer length multiple of 4. */
  444.  
  445.   bufLength = (bufLength + 3) >> 2;
  446.  
  447.   /* Allocate memory for new structure. */
  448.  
  449.   new = (VidStream *) malloc(sizeof(VidStream));
  450.  
  451.   /* Initialize pointers to extension and user data. */
  452.  
  453.   new->group.ext_data = new->group.user_data =
  454.     new->picture.extra_info = new->picture.user_data =
  455.     new->picture.ext_data = new->slice.extra_info =
  456.     new->ext_data = new->user_data = NULL;
  457.  
  458.   /* Copy default intra matrix. */
  459.  
  460.   for (i = 0; i < 8; i++) {
  461.     for (j = 0; j < 8; j++) {
  462.       new->intra_quant_matrix[j][i] = default_intra_matrix[i * 8 + j];
  463.     }
  464.   }
  465.  
  466.   /* Initialize crop table. */
  467.  
  468.   for (i = (-MAX_NEG_CROP); i < NUM_CROP_ENTRIES - MAX_NEG_CROP; i++) {
  469.     if (i <= 0) {
  470.       cropTbl[i + MAX_NEG_CROP] = 0;
  471.     } else if (i >= 255) {
  472.       cropTbl[i + MAX_NEG_CROP] = 255;
  473.     } else {
  474.       cropTbl[i + MAX_NEG_CROP] = i;
  475.     }
  476.   }
  477.  
  478.   /* Initialize non intra quantization matrix. */
  479.  
  480.   for (i = 0; i < 8; i++) {
  481.     for (j = 0; j < 8; j++) {
  482.       new->non_intra_quant_matrix[j][i] = 16;
  483.     }
  484.   }
  485.  
  486.   /* Initialize pointers to image spaces. */
  487.  
  488.   new->current = new->past = new->future = NULL;
  489.   for (i = 0; i < RING_BUF_SIZE; i++) {
  490.     new->ring[i] = NULL;
  491.   }
  492.  
  493.   /* Create buffer. */
  494.  
  495.   new->buf_start = (unsigned int *) malloc(bufLength * 4);
  496.  
  497.   /*
  498.    * Set max_buf_length to one less than actual length to deal with messy
  499.    * data without proper seq. end codes.
  500.    */
  501.  
  502.   new->max_buf_length = bufLength - 1;
  503.  
  504.   /* Initialize bitstream i/o fields. */
  505.  
  506.   new->bit_offset = 0;
  507.   new->buf_length = 0;
  508.   new->buffer = new->buf_start;
  509.  
  510.  
  511.   /* Return structure. */
  512.  
  513.   return new;
  514. }
  515.  
  516.  
  517.  
  518. /*
  519.  *--------------------------------------------------------------
  520.  *
  521.  * DestroyVidStream --
  522.  *
  523.  *    Deallocates a VidStream structure.
  524.  *
  525.  * Results:
  526.  *      None.
  527.  *
  528.  * Side effects:
  529.  *    None.
  530.  *
  531.  *--------------------------------------------------------------
  532.  */
  533. void
  534. DestroyVidStream(astream)
  535.   VidStream *astream;
  536. {
  537.   int i;
  538.  
  539.   if (astream->ext_data != NULL)
  540.     free(astream->ext_data);
  541.  
  542.   if (astream->user_data != NULL)
  543.     free(astream->user_data);
  544.  
  545.   if (astream->group.ext_data != NULL)
  546.     free(astream->group.ext_data);
  547.  
  548.   if (astream->group.user_data != NULL)
  549.     free(astream->group.user_data);
  550.  
  551.   if (astream->picture.extra_info != NULL)
  552.     free(astream->picture.extra_info);
  553.  
  554.   if (astream->picture.ext_data != NULL)
  555.     free(astream->picture.ext_data);
  556.  
  557.   if (astream->picture.user_data != NULL)
  558.     free(astream->picture.user_data);
  559.  
  560.   if (astream->slice.extra_info != NULL)
  561.     free(astream->slice.extra_info);
  562.  
  563.   if (astream->buf_start != NULL)
  564.     free(astream->buf_start);
  565.  
  566.   for (i = 0; i < RING_BUF_SIZE; i++) {
  567.     if (astream->ring[i] != NULL) {
  568.       DestroyPictImage(astream->ring[i]);
  569.       astream->ring[i] = NULL;
  570.     }
  571.   }
  572.  
  573.   free((char *) astream);
  574. }
  575.  
  576.  
  577.  
  578.  
  579. /*
  580.  *--------------------------------------------------------------
  581.  *
  582.  * NewPictImage --
  583.  *
  584.  *    Allocates and initializes a PictImage structure.
  585.  *      The width and height of the image space are passed in
  586.  *      as parameters.
  587.  *
  588.  * Results:
  589.  *    A pointer to the new PictImage structure.
  590.  *
  591.  * Side effects:
  592.  *    None.
  593.  *
  594.  *--------------------------------------------------------------
  595.  */
  596.  
  597. PictImage *
  598. NewPictImage(width, height)
  599.   unsigned int width, height;
  600. {
  601.   PictImage *new;
  602.  
  603.   /* Allocate memory space for new structure. */
  604.  
  605.   new = (PictImage *) malloc(sizeof(PictImage));
  606.  
  607.  
  608.   /* Allocate memory for image spaces. */
  609.  
  610.   new->display = (unsigned char *) malloc(width * height);
  611.  
  612.   new->luminance = (unsigned char *) malloc(width * height);
  613.   new->Cr = (unsigned char *) malloc(width * height / 4);
  614.   new->Cb = (unsigned char *) malloc(width * height / 4);
  615.  
  616.   /* Reset locked flag. */
  617.  
  618.   new->locked = 0;
  619.  
  620.   /* Return pointer to new structure. */
  621.  
  622.   return new;
  623. }
  624.  
  625.  
  626.  
  627. /*
  628.  *--------------------------------------------------------------
  629.  *
  630.  * DestroyPictImage --
  631.  *
  632.  *    Deallocates a PictImage structure.
  633.  *
  634.  * Results:
  635.  *      None.
  636.  *
  637.  * Side effects:
  638.  *    None.
  639.  *
  640.  *--------------------------------------------------------------
  641.  */
  642. void
  643. DestroyPictImage(apictimage)
  644.   PictImage *apictimage;
  645. {
  646.   if (apictimage->luminance != NULL) {
  647.     free(apictimage->luminance);
  648.   }
  649.   if (apictimage->Cr != NULL) {
  650.     free(apictimage->Cr);
  651.   }
  652.   if (apictimage->Cb != NULL) {
  653.     free(apictimage->Cb);
  654.   }
  655.  
  656.   if (apictimage->display != NULL) {
  657.     free(apictimage->display);
  658.   }
  659.   free(apictimage);
  660. }
  661.  
  662.  
  663.  
  664. /*
  665.  *--------------------------------------------------------------
  666.  *
  667.  * mpegVidRsrc --
  668.  *
  669.  *      Parses bit stream until MB_QUANTUM number of
  670.  *      macroblocks have been decoded or current slice or
  671.  *      picture ends, whichever comes first. If the start
  672.  *      of a frame is encountered, the frame is time stamped
  673.  *      with the value passed in time_stamp. If the value
  674.  *      passed in buffer is not null, the video stream buffer
  675.  *      is set to buffer and the length of the buffer is
  676.  *      expected in value passed in through length. The current
  677.  *      video stream is set to vid_stream. If vid_stream
  678.  *      is passed as NULL, a new VidStream structure is created
  679.  *      and initialized and used as the current video stream.
  680.  *
  681.  * Results:
  682.  *      A pointer to the video stream structure used.
  683.  *
  684.  * Side effects:
  685.  *      Bit stream is irreversibly parsed. If a picture is completed,
  686.  *      a function is called to display the frame at the correct time.
  687.  *
  688.  *--------------------------------------------------------------
  689.  */
  690.  
  691. VidStream *
  692. mpegVidRsrc(time_stamp, vid_stream)
  693.   TimeStamp time_stamp;
  694.   VidStream *vid_stream;
  695. {
  696.   static int first = 1;
  697.   unsigned int data;
  698.   int i, status;
  699.  
  700.   /* If vid_stream is null, create new VidStream structure. */
  701.  
  702.   if (vid_stream == NULL) {
  703.     return NULL;
  704.   }
  705.   /*
  706.    * Set global curVidStream to vid_stream. Necessary because bit i/o use
  707.    * curVidStream and are not passed vid_stream. Also set global bitstream
  708.    * parameters.
  709.    */
  710.  
  711.   curVidStream = vid_stream;
  712.   bitOffset = curVidStream->bit_offset;
  713. #ifdef UTIL2
  714.   curBits = *curVidStream->buffer << bitOffset;
  715. #else
  716.   curBits = *curVidStream->buffer;
  717. #endif
  718.   bufLength = curVidStream->buf_length;
  719.   bitBuffer = curVidStream->buffer;
  720.  
  721.   /*
  722.    * If called for the first time, find start code, make sure it is a
  723.    * sequence start code.
  724.    */
  725.  
  726.   if (first) {
  727.     next_start_code();
  728.     show_bits32(data);
  729.     if (data != SEQ_START_CODE) {
  730.       fprintf(stderr, "This is not an MPEG stream.");
  731.       DestroyVidStream(curVidStream);
  732.       exit(1);
  733.     }
  734.     first = 0;
  735.   }
  736.   /* Get next 32 bits (size of start codes). */
  737.  
  738.   show_bits32(data);
  739.  
  740.   /*
  741.    * Process according to start code (or parse macroblock if not a start code
  742.    * at all.
  743.    */
  744.  
  745.   switch (data) {
  746.  
  747.   case SEQ_END_CODE:
  748.  
  749.     /* Display last frame. */
  750.  
  751.     if (vid_stream->future != NULL) {
  752.       vid_stream->current = vid_stream->future;
  753.     }
  754.     
  755.     /* Sequence done. Do the right thing. For right now, exit. */
  756.  
  757.  
  758.     PrintAllStats();
  759.     PrintTimeInfo();
  760.  
  761.     if (loopFlag)
  762.       longjmp(env, 1);
  763.  
  764.     DestroyVidStream(curVidStream);
  765.     exit(0);
  766.     break;
  767.  
  768.   case SEQ_START_CODE:
  769.  
  770.     /* Sequence start code. Parse sequence header. */
  771.  
  772.     if (ParseSeqHead(vid_stream) != PARSE_OK)
  773.       goto error;
  774.  
  775.     /*
  776.      * Return after sequence start code so that application above can use
  777.      * info in header.
  778.      */
  779.  
  780.     goto done;
  781.  
  782.   case GOP_START_CODE:
  783.  
  784.     /* Group of Pictures start code. Parse gop header. */
  785.  
  786.     if (ParseGOP(vid_stream) != PARSE_OK)
  787.       goto error;
  788.  
  789.  
  790.   case PICTURE_START_CODE:
  791.  
  792.     /* Picture start code. Parse picture header and first slice header. */
  793.  
  794.     status = ParsePicture(vid_stream, time_stamp);
  795.  
  796.     if (status == SKIP_PICTURE) {
  797.       next_start_code();
  798.       fprintf(stderr, "Skipping picture...");
  799.       while (!next_bits(32, PICTURE_START_CODE)) {
  800.     if (next_bits(32, GOP_START_CODE))
  801.       break;
  802.     else if (next_bits(32, SEQ_END_CODE))
  803.       break;
  804.     flush_bits(24);
  805.     next_start_code();
  806.       }
  807.       fprintf(stderr, "Done.\n");
  808.       goto done;
  809.     } else if (status != PARSE_OK)
  810.       goto error;
  811.  
  812.  
  813.     if (ParseSlice(vid_stream) != PARSE_OK)
  814.       goto error;
  815.     break;
  816.  
  817.   default:
  818.  
  819.     /* Check for slice start code. */
  820.  
  821.     if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) {
  822.  
  823.       /* Slice start code. Parse slice header. */
  824.  
  825.       if (ParseSlice(vid_stream) != PARSE_OK)
  826.     goto error;
  827.     }
  828.     break;
  829.   }
  830.  
  831.   /* Parse next MB_QUANTUM macroblocks. */
  832.  
  833.   for (i = 0; i < MB_QUANTUM; i++) {
  834.  
  835.     /* Check to see if actually a startcode and not a macroblock. */
  836.  
  837.     if (!next_bits(23, 0x00000000)) {
  838.  
  839.       /* Not start code. Parse Macroblock. */
  840.  
  841.       if (ParseMacroBlock(vid_stream) != PARSE_OK)
  842.     goto error;
  843.  
  844.       if (showmb_flag) 
  845.     ShowOutputVal(vid_stream); 
  846.  
  847.     } else {
  848.  
  849.       /* Not macroblock, actually start code. Get start code. */
  850.  
  851.       next_start_code();
  852.       show_bits32(data);
  853.  
  854.       /*
  855.        * If start code is outside range of slice start codes, frame is
  856.        * complete, display frame.
  857.        */
  858.  
  859.       if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) {
  860.  
  861.     EndTime();
  862.     stat_a[0].totsize += bitCountRead() - pictureSizeCount;
  863.  
  864.     CollectStats();
  865.  
  866.     DoPictureDisplay(vid_stream);
  867.       }
  868.       break;
  869.     }
  870.   }
  871.  
  872.   /* Return pointer to video stream structure. */
  873.  
  874.   goto done;
  875.  
  876. error:
  877.   fprintf(stderr, "Error!!!!\n");
  878.   next_start_code();
  879.   goto done;
  880.  
  881. done:
  882.  
  883.   /* Copy global bit i/o variables back into vid_stream. */
  884.  
  885.   vid_stream->buffer = bitBuffer;
  886.   vid_stream->buf_length = bufLength;
  887.   vid_stream->bit_offset = bitOffset;
  888.  
  889.   return vid_stream;
  890.  
  891. }
  892.  
  893.  
  894.  
  895. /*
  896.  *--------------------------------------------------------------
  897.  *
  898.  * ParseSeqHead --
  899.  *
  900.  *      Assumes bit stream is at the begining of the sequence
  901.  *      header start code. Parses off the sequence header.
  902.  *
  903.  * Results:
  904.  *      Fills the vid_stream structure with values derived and
  905.  *      decoded from the sequence header. Allocates the pict image
  906.  *      structures based on the dimensions of the image space
  907.  *      found in the sequence header.
  908.  *
  909.  * Side effects:
  910.  *      Bit stream irreversibly parsed off.
  911.  *
  912.  *--------------------------------------------------------------
  913.  */
  914.  
  915. static int
  916. ParseSeqHead(vid_stream)
  917.   VidStream *vid_stream;
  918. {
  919.  
  920.   unsigned int data;
  921.   int i;
  922.  
  923.   /* Flush off sequence start code. */
  924.  
  925.   flush_bits32;
  926.  
  927.   /* Get horizontal size of image space. */
  928.  
  929.   get_bits12(data);
  930.   vid_stream->h_size = data;
  931.  
  932.   /* Get vertical size of image space. */
  933.  
  934.   get_bits12(data);
  935.   vid_stream->v_size = data;
  936.  
  937.   /* Calculate macroblock width and height of image space. */
  938.  
  939.   vid_stream->mb_width = (vid_stream->h_size + 15) / 16;
  940.   vid_stream->mb_height = (vid_stream->v_size + 15) / 16;
  941.  
  942.   /* If dither type is MBORDERED allocate ditherFlags. */
  943.  
  944.   if (ditherType == MBORDERED_DITHER) {
  945.     ditherFlags = (char *) malloc(vid_stream->mb_width*vid_stream->mb_height);
  946.   }
  947.  
  948.   /* Initialize lmaxx, lmaxy, cmaxx, cmaxy. */
  949.  
  950.   lmaxx = vid_stream->mb_width*16-1;
  951.   lmaxy = vid_stream->mb_height*16-1;
  952.   cmaxx = vid_stream->mb_width*8-1;
  953.   cmaxy = vid_stream->mb_height*8-1;
  954.  
  955.   /*
  956.    * Initialize ring buffer of pict images now that dimensions of image space
  957.    * are known.
  958.    */
  959.  
  960.  
  961.   if (vid_stream->ring[0] == NULL) {
  962.     for (i = 0; i < RING_BUF_SIZE; i++) {
  963.       vid_stream->ring[i] = NewPictImage(vid_stream->mb_width * 16,
  964.                      vid_stream->mb_height * 16);
  965.     }
  966.   }
  967.  
  968.   /* Parse of aspect ratio code. */
  969.  
  970.   get_bits4(data);
  971.   vid_stream->aspect_ratio = (unsigned char) data;
  972.  
  973.   /* Parse off picture rate code. */
  974.  
  975.   get_bits4(data);
  976.   vid_stream->picture_rate = (unsigned char) data;
  977.  
  978.   /* Parse off bit rate. */
  979.  
  980.   get_bits18(data);
  981.   vid_stream->bit_rate = data;
  982.  
  983.   /* Flush marker bit. */
  984.  
  985.   flush_bits(1);
  986.  
  987.   /* Parse off vbv buffer size. */
  988.  
  989.   get_bits10(data);
  990.   vid_stream->vbv_buffer_size = data;
  991.  
  992.   /* Parse off contrained parameter flag. */
  993.  
  994.   get_bits1(data);
  995.   if (data) {
  996.     vid_stream->const_param_flag = TRUE;
  997.   } else
  998.     vid_stream->const_param_flag = FALSE;
  999.  
  1000.   /*
  1001.    * If intra_quant_matrix_flag set, parse off intra quant matrix values.
  1002.    */
  1003.  
  1004.   get_bits1(data);
  1005.   if (data) {
  1006.     for (i = 0; i < 64; i++) {
  1007.       get_bits8(data);
  1008.  
  1009.       vid_stream->intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
  1010.     (unsigned char) data;
  1011.     }
  1012.   }
  1013.   /*
  1014.    * If non intra quant matrix flag set, parse off non intra quant matrix
  1015.    * values.
  1016.    */
  1017.  
  1018.   get_bits1(data);
  1019.   if (data) {
  1020.     for (i = 0; i < 64; i++) {
  1021.       get_bits8(data);
  1022.  
  1023.       vid_stream->non_intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] =
  1024.     (unsigned char) data;
  1025.     }
  1026.   }
  1027.   /* Go to next start code. */
  1028.  
  1029.   next_start_code();
  1030.  
  1031.   /*
  1032.    * If next start code is extension start code, parse off extension data.
  1033.    */
  1034.  
  1035.   if (next_bits(32, EXT_START_CODE)) {
  1036.     flush_bits32;
  1037.     if (vid_stream->ext_data != NULL) {
  1038.       free(vid_stream->ext_data);
  1039.       vid_stream->ext_data = NULL;
  1040.     }
  1041.     vid_stream->ext_data = get_ext_data();
  1042.   }
  1043.   /* If next start code is user start code, parse off user data. */
  1044.  
  1045.   if (next_bits(32, USER_START_CODE)) {
  1046.     flush_bits32;
  1047.     if (vid_stream->user_data != NULL) {
  1048.       free(vid_stream->user_data);
  1049.       vid_stream->user_data = NULL;
  1050.     }
  1051.     vid_stream->user_data = get_ext_data();
  1052.   }
  1053.   return PARSE_OK;
  1054. }
  1055.  
  1056.  
  1057.  
  1058. /*
  1059.  *--------------------------------------------------------------
  1060.  *
  1061.  * ParseGOP --
  1062.  *
  1063.  *      Parses of group of pictures header from bit stream
  1064.  *      associated with vid_stream.
  1065.  *
  1066.  * Results:
  1067.  *      Values in gop header placed into video stream structure.
  1068.  *
  1069.  * Side effects:
  1070.  *      Bit stream irreversibly parsed.
  1071.  *
  1072.  *--------------------------------------------------------------
  1073.  */
  1074.  
  1075. static int
  1076. ParseGOP(vid_stream)
  1077.   VidStream *vid_stream;
  1078. {
  1079.   unsigned int data;
  1080.  
  1081.   /* Flush group of pictures start code. WWWWWWOOOOOOOSSSSSSHHHHH!!! */
  1082.  
  1083.   flush_bits32;
  1084.  
  1085.   /* Parse off drop frame flag. */
  1086.  
  1087.   get_bits1(data);
  1088.   if (data) {
  1089.     vid_stream->group.drop_flag = TRUE;
  1090.   } else
  1091.     vid_stream->group.drop_flag = FALSE;
  1092.  
  1093.   /* Parse off hour component of time code. */
  1094.  
  1095.   get_bits5(data);
  1096.   vid_stream->group.tc_hours = data;
  1097.  
  1098.   /* Parse off minute component of time code. */
  1099.  
  1100.   get_bits6(data);
  1101.   vid_stream->group.tc_minutes = data;
  1102.  
  1103.   /* Flush marker bit. */
  1104.  
  1105.   flush_bits(1);
  1106.  
  1107.   /* Parse off second component of time code. */
  1108.  
  1109.   get_bits6(data);
  1110.   vid_stream->group.tc_seconds = data;
  1111.  
  1112.   /* Parse off picture count component of time code. */
  1113.  
  1114.   get_bits6(data);
  1115.   vid_stream->group.tc_pictures = data;
  1116.  
  1117.   /* Parse off closed gop and broken link flags. */
  1118.  
  1119.   get_bits2(data);
  1120.   if (data > 1) {
  1121.     vid_stream->group.closed_gop = TRUE;
  1122.     if (data > 2) {
  1123.       vid_stream->group.broken_link = TRUE;
  1124.     } else
  1125.       vid_stream->group.broken_link = FALSE;
  1126.   } else {
  1127.     vid_stream->group.closed_gop = FALSE;
  1128.     if (data) {
  1129.       vid_stream->group.broken_link = TRUE;
  1130.     } else
  1131.       vid_stream->group.broken_link = FALSE;
  1132.   }
  1133.  
  1134.   /* Goto next start code. */
  1135.  
  1136.   next_start_code();
  1137.  
  1138.   /* If next start code is extension data, parse off extension data. */
  1139.  
  1140.   if (next_bits(32, EXT_START_CODE)) {
  1141.     flush_bits32;
  1142.     if (vid_stream->group.ext_data != NULL) {
  1143.       free(vid_stream->group.ext_data);
  1144.       vid_stream->group.ext_data = NULL;
  1145.     }
  1146.     vid_stream->group.ext_data = get_ext_data();
  1147.   }
  1148.   /* If next start code is user data, parse off user data. */
  1149.  
  1150.   if (next_bits(32, USER_START_CODE)) {
  1151.     flush_bits32;
  1152.     if (vid_stream->group.user_data != NULL) {
  1153.       free(vid_stream->group.user_data);
  1154.       vid_stream->group.user_data = NULL;
  1155.     }
  1156.     vid_stream->group.user_data = get_ext_data();
  1157.   }
  1158.   return PARSE_OK;
  1159. }
  1160.  
  1161.  
  1162.  
  1163. /*
  1164.  *--------------------------------------------------------------
  1165.  *
  1166.  * ParsePicture --
  1167.  *
  1168.  *      Parses picture header. Marks picture to be presented
  1169.  *      at particular time given a time stamp.
  1170.  *
  1171.  * Results:
  1172.  *      Values from picture header put into video stream structure.
  1173.  *
  1174.  * Side effects:
  1175.  *      Bit stream irreversibly parsed.
  1176.  *
  1177.  *--------------------------------------------------------------
  1178.  */
  1179.  
  1180. static int
  1181. ParsePicture(vid_stream, time_stamp)
  1182.   VidStream *vid_stream;
  1183.   TimeStamp time_stamp;
  1184. {
  1185.   unsigned int data;
  1186.   int i;
  1187.  
  1188.   /* Flush header start code. */
  1189.   flush_bits32;
  1190.  
  1191.   /* Parse off temporal reference. */
  1192.   get_bits10(data);
  1193.   vid_stream->picture.temp_ref = data;
  1194.  
  1195.   /* Parse of picture type. */
  1196.   get_bits3(data);
  1197.   vid_stream->picture.code_type = data;
  1198.  
  1199.   /* echo frame type on screen */
  1200.  
  1201.   printtype(vid_stream);
  1202.  
  1203.   if ((vid_stream->picture.code_type == B_TYPE) &&
  1204.       (No_B_Flag ||
  1205.        (vid_stream->past == NULL) ||
  1206.        (vid_stream->future == NULL))) 
  1207.     return SKIP_PICTURE;
  1208.  
  1209.   if ((vid_stream->picture.code_type == P_TYPE) &&
  1210.       (No_P_Flag || (vid_stream->future == NULL)))
  1211.     return SKIP_PICTURE;
  1212.  
  1213.   StartTime();
  1214.   stat_a[0].frametype = vid_stream->picture.code_type;
  1215.   stat_a[0].number = 1;
  1216.   stat_a[0].totsize = 45;
  1217.   pictureSizeCount = bitCountRead();
  1218.  
  1219.   /* Parse off vbv buffer delay value. */
  1220.   get_bits16(data);
  1221.   vid_stream->picture.vbv_delay = data;
  1222.  
  1223.   /* If P or B type frame... */
  1224.  
  1225.   if ((vid_stream->picture.code_type == 2) || (vid_stream->picture.code_type == 3)) {
  1226.  
  1227.     /* Parse off forward vector full pixel flag. */
  1228.     get_bits1(data);
  1229.     if (data)
  1230.       vid_stream->picture.full_pel_forw_vector = TRUE;
  1231.     else
  1232.       vid_stream->picture.full_pel_forw_vector = FALSE;
  1233.  
  1234.     /* Parse of forw_r_code. */
  1235.     get_bits3(data);
  1236.  
  1237.     /* Decode forw_r_code into forw_r_size and forw_f. */
  1238.  
  1239.     vid_stream->picture.forw_r_size = data - 1;
  1240.     vid_stream->picture.forw_f = (1 << vid_stream->picture.forw_r_size);
  1241.   }
  1242.   /* If B type frame... */
  1243.  
  1244.   if (vid_stream->picture.code_type == 3) {
  1245.  
  1246.     /* Parse off back vector full pixel flag. */
  1247.     get_bits1(data);
  1248.     if (data)
  1249.       vid_stream->picture.full_pel_back_vector = TRUE;
  1250.     else
  1251.       vid_stream->picture.full_pel_back_vector = FALSE;
  1252.  
  1253.     /* Parse off back_r_code. */
  1254.     get_bits3(data);
  1255.  
  1256.     /* Decode back_r_code into back_r_size and back_f. */
  1257.  
  1258.     vid_stream->picture.back_r_size = data - 1;
  1259.     vid_stream->picture.back_f = (1 << vid_stream->picture.back_r_size);
  1260.   }
  1261.   /* Get extra bit picture info. */
  1262.  
  1263.   if (vid_stream->picture.extra_info != NULL) {
  1264.     free(vid_stream->picture.extra_info);
  1265.     vid_stream->picture.extra_info = NULL;
  1266.   }
  1267.   vid_stream->picture.extra_info = get_extra_bit_info();
  1268.  
  1269.   /* Goto next start code. */
  1270.   next_start_code();
  1271.  
  1272.   /* If start code is extension start code, parse off extension data. */
  1273.  
  1274.   if (next_bits(32, EXT_START_CODE)) {
  1275.     flush_bits32;
  1276.  
  1277.     if (vid_stream->picture.ext_data != NULL) {
  1278.       free(vid_stream->picture.ext_data);
  1279.       vid_stream->picture.ext_data = NULL;
  1280.     }
  1281.     vid_stream->picture.ext_data = get_ext_data();
  1282.   }
  1283.   /* If start code is user start code, parse off user data. */
  1284.  
  1285.   if (next_bits(32, USER_START_CODE)) {
  1286.     flush_bits32;
  1287.  
  1288.     if (vid_stream->picture.user_data != NULL) {
  1289.       free(vid_stream->picture.user_data);
  1290.       vid_stream->picture.user_data = NULL;
  1291.     }
  1292.     vid_stream->picture.user_data = get_ext_data();
  1293.   }
  1294.   /* Find a pict image structure in ring buffer not currently locked. */
  1295.  
  1296.   i = 0;
  1297.  
  1298.   while (vid_stream->ring[i]->locked != 0) {
  1299.     if (++i >= RING_BUF_SIZE) {
  1300.       printf("Fatal error. Ring buffer full.");
  1301.       exit(1);
  1302.     }
  1303.   }
  1304.  
  1305.   /* Set current pict image structure to the one just found in ring. */
  1306.  
  1307.   vid_stream->current = vid_stream->ring[i];
  1308.  
  1309.   /* Set time stamp. */
  1310.  
  1311.   vid_stream->current->show_time = time_stamp;
  1312.  
  1313.   /* Reset past macroblock address field. */
  1314.  
  1315.   vid_stream->mblock.past_mb_addr = -1;
  1316.  
  1317.   return PARSE_OK;
  1318. }
  1319.  
  1320.  
  1321.  
  1322. /*
  1323.  *--------------------------------------------------------------
  1324.  *
  1325.  * ParseSlice --
  1326.  *
  1327.  *      Parses off slice header.
  1328.  *
  1329.  * Results:
  1330.  *      Values found in slice header put into video stream structure.
  1331.  *
  1332.  * Side effects:
  1333.  *      Bit stream irreversibly parsed.
  1334.  *
  1335.  *--------------------------------------------------------------
  1336.  */
  1337.  
  1338. static int
  1339. ParseSlice(vid_stream)
  1340.   VidStream *vid_stream;
  1341. {
  1342.   unsigned int data;
  1343.  
  1344.   /* Flush slice start code. */
  1345.  
  1346.   flush_bits(24);
  1347.  
  1348.   /* Parse off slice vertical position. */
  1349.  
  1350.   get_bits8(data);
  1351.   vid_stream->slice.vert_pos = data;
  1352.  
  1353.   /* Parse off quantization scale. */
  1354.  
  1355.   get_bits5(data);
  1356.   vid_stream->slice.quant_scale = data;
  1357.  
  1358.   /* Parse off extra bit slice info. */
  1359.  
  1360.   if (vid_stream->slice.extra_info != NULL) {
  1361.     free(vid_stream->slice.extra_info);
  1362.     vid_stream->slice.extra_info = NULL;
  1363.   }
  1364.   vid_stream->slice.extra_info = get_extra_bit_info();
  1365.  
  1366.   /* Reset past intrablock address. */
  1367.  
  1368.   vid_stream->mblock.past_intra_addr = -2;
  1369.  
  1370.   /* Reset previous recon motion vectors. */
  1371.  
  1372.   vid_stream->mblock.recon_right_for_prev = 0;
  1373.   vid_stream->mblock.recon_down_for_prev = 0;
  1374.   vid_stream->mblock.recon_right_back_prev = 0;
  1375.   vid_stream->mblock.recon_down_back_prev = 0;
  1376.  
  1377.   /* Reset macroblock address. */
  1378.  
  1379.   vid_stream->mblock.mb_address = ((vid_stream->slice.vert_pos - 1) *
  1380.                    vid_stream->mb_width) - 1;
  1381.  
  1382.   /* Reset past dct dc y, cr, and cb values. */
  1383.  
  1384.   vid_stream->block.dct_dc_y_past = 1024;
  1385.   vid_stream->block.dct_dc_cr_past = 1024;
  1386.   vid_stream->block.dct_dc_cb_past = 1024;
  1387.  
  1388.   return PARSE_OK;
  1389. }
  1390.  
  1391.  
  1392.  
  1393. /*
  1394.  *--------------------------------------------------------------
  1395.  *
  1396.  * ParseMacroBlock --
  1397.  *
  1398.  *      Parseoff macroblock. Reconstructs DCT values. Applies
  1399.  *      inverse DCT, reconstructs motion vectors, calculates and
  1400.  *      set pixel values for macroblock in current pict image
  1401.  *      structure.
  1402.  *
  1403.  * Results:
  1404.  *      Here's where everything really happens. Welcome to the
  1405.  *      heart of darkness.
  1406.  *
  1407.  * Side effects:
  1408.  *      Bit stream irreversibly parsed off.
  1409.  *
  1410.  *--------------------------------------------------------------
  1411.  */
  1412.  
  1413. static int
  1414. ParseMacroBlock(vid_stream)
  1415.   VidStream *vid_stream;
  1416. {
  1417.   int addr_incr;
  1418.   unsigned int data;
  1419.   int mask, i, recon_right_for, recon_down_for, recon_right_back,
  1420.       recon_down_back;
  1421.   int zero_block_flag;
  1422.   BOOLEAN mb_quant, mb_motion_forw, mb_motion_back, mb_pattern;
  1423.   int no_dith_flag = 0;
  1424.  
  1425.   mbSizeCount = bitCountRead();
  1426.  
  1427.   /*
  1428.    * Parse off macroblock address increment and add to macroblock address.
  1429.    */
  1430.   do {
  1431.     DecodeMBAddrInc(addr_incr);
  1432.     if (addr_incr == MB_ESCAPE) {
  1433.       vid_stream->mblock.mb_address += 33;
  1434.       addr_incr = MB_STUFFING;
  1435.     }
  1436.   } while (addr_incr == MB_STUFFING);
  1437.   vid_stream->mblock.mb_address += addr_incr;
  1438.  
  1439.   if (vid_stream->mblock.mb_address > (vid_stream->mb_height *
  1440.                        vid_stream->mb_width - 1))
  1441.     return SKIP_TO_START_CODE;
  1442.  
  1443.   /*
  1444.    * If macroblocks have been skipped, process skipped macroblocks.
  1445.    */
  1446.  
  1447.   if (vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr > 1) {
  1448.     if (vid_stream->picture.code_type == P_TYPE)
  1449.       ProcessSkippedPFrameMBlocks(vid_stream);
  1450.     else if (vid_stream->picture.code_type == B_TYPE)
  1451.       ProcessSkippedBFrameMBlocks(vid_stream);
  1452.   }
  1453.   /* Set past macroblock address to current macroblock address. */
  1454.   vid_stream->mblock.past_mb_addr = vid_stream->mblock.mb_address;
  1455.  
  1456.   /* Based on picture type decode macroblock type. */
  1457.   switch (vid_stream->picture.code_type) {
  1458.   case I_TYPE:
  1459.     DecodeMBTypeI(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1460.           vid_stream->mblock.mb_intra);
  1461.     break;
  1462.  
  1463.   case P_TYPE:
  1464.     DecodeMBTypeP(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1465.           vid_stream->mblock.mb_intra);
  1466.     break;
  1467.  
  1468.   case B_TYPE:
  1469.     DecodeMBTypeB(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern,
  1470.           vid_stream->mblock.mb_intra);
  1471.     break;
  1472.   }
  1473.  
  1474.   /* If quantization flag set, parse off new quantization scale. */
  1475.  
  1476.   if (mb_quant == TRUE) {
  1477.     get_bits5(data);
  1478.     vid_stream->slice.quant_scale = data;
  1479.   }
  1480.   /* If forward motion vectors exist... */
  1481.   if (mb_motion_forw == TRUE) {
  1482.  
  1483.     /* Parse off and decode horizontal forward motion vector. */
  1484.     DecodeMotionVectors(vid_stream->mblock.motion_h_forw_code);
  1485.  
  1486.     /* If horiz. forward r data exists, parse off. */
  1487.  
  1488.     if ((vid_stream->picture.forw_f != 1) &&
  1489.     (vid_stream->mblock.motion_h_forw_code != 0)) {
  1490.       get_bitsn(vid_stream->picture.forw_r_size, data);
  1491.       vid_stream->mblock.motion_h_forw_r = data;
  1492.     }
  1493.     /* Parse off and decode vertical forward motion vector. */
  1494.     DecodeMotionVectors(vid_stream->mblock.motion_v_forw_code);
  1495.  
  1496.     /* If vert. forw. r data exists, parse off. */
  1497.  
  1498.     if ((vid_stream->picture.forw_f != 1) &&
  1499.     (vid_stream->mblock.motion_v_forw_code != 0)) {
  1500.       get_bitsn(vid_stream->picture.forw_r_size, data);
  1501.       vid_stream->mblock.motion_v_forw_r = data;
  1502.     }
  1503.   }
  1504.   /* If back motion vectors exist... */
  1505.   if (mb_motion_back == TRUE) {
  1506.  
  1507.     /* Parse off and decode horiz. back motion vector. */
  1508.     DecodeMotionVectors(vid_stream->mblock.motion_h_back_code);
  1509.  
  1510.     /* If horiz. back r data exists, parse off. */
  1511.  
  1512.     if ((vid_stream->picture.back_f != 1) &&
  1513.     (vid_stream->mblock.motion_h_back_code != 0)) {
  1514.       get_bitsn(vid_stream->picture.back_r_size, data);
  1515.       vid_stream->mblock.motion_h_back_r = data;
  1516.     }
  1517.     /* Parse off and decode vert. back motion vector. */
  1518.     DecodeMotionVectors(vid_stream->mblock.motion_v_back_code);
  1519.  
  1520.     /* If vert. back r data exists, parse off. */
  1521.  
  1522.     if ((vid_stream->picture.back_f != 1) &&
  1523.     (vid_stream->mblock.motion_v_back_code != 0)) {
  1524.       get_bitsn(vid_stream->picture.back_r_size, data);
  1525.       vid_stream->mblock.motion_v_back_r = data;
  1526.     }
  1527.   }
  1528.   if (vid_stream->mblock.mb_intra) {
  1529.     stat_a[0].i_mbnum++;
  1530.     mbCBPPtr = stat_a[0].i_mbcbp;
  1531.     mbCoeffPtr = stat_a[0].i_mbcoeff;
  1532.     mbSizePtr = &(stat_a[0].i_mbsize);
  1533.   } else if (mb_motion_back && mb_motion_forw) {
  1534.     stat_a[0].bi_mbnum++;
  1535.     mbCBPPtr = stat_a[0].bi_mbcbp;
  1536.     mbCoeffPtr = stat_a[0].bi_mbcoeff;
  1537.     mbSizePtr = &(stat_a[0].bi_mbsize);
  1538.   } else if (mb_motion_back) {
  1539.     stat_a[0].b_mbnum++;
  1540.     mbCBPPtr = stat_a[0].b_mbcbp;
  1541.     mbCoeffPtr = stat_a[0].b_mbcoeff;
  1542.     mbSizePtr = &(stat_a[0].b_mbsize);
  1543.   } else {
  1544.     stat_a[0].p_mbnum++;
  1545.     mbCBPPtr = stat_a[0].p_mbcbp;
  1546.     mbCoeffPtr = stat_a[0].p_mbcoeff;
  1547.     mbSizePtr = &(stat_a[0].p_mbsize);
  1548.   }
  1549.  
  1550.   /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
  1551.   if (mb_pattern == TRUE) {
  1552.     DecodeCBP(vid_stream->mblock.cbp);
  1553.   }
  1554.   /* Otherwise, set CBP to zero. */
  1555.   else
  1556.     vid_stream->mblock.cbp = 0;
  1557.  
  1558.  
  1559.   mbCBPPtr[vid_stream->mblock.cbp]++;
  1560.  
  1561.   /* Reconstruct motion vectors depending on picture type. */
  1562.   if (vid_stream->picture.code_type == P_TYPE) {
  1563.  
  1564.     /*
  1565.      * If no forw motion vectors, reset previous and current vectors to 0.
  1566.      */
  1567.  
  1568.     if (!mb_motion_forw) {
  1569.       recon_right_for = 0;
  1570.       recon_down_for = 0;
  1571.       vid_stream->mblock.recon_right_for_prev = 0;
  1572.       vid_stream->mblock.recon_down_for_prev = 0;
  1573.     }
  1574.     /*
  1575.      * Otherwise, compute new forw motion vectors. Reset previous vectors to
  1576.      * current vectors.
  1577.      */
  1578.  
  1579.     else {
  1580.       ComputeForwVector(&recon_right_for, &recon_down_for);
  1581.     }
  1582.   }
  1583.   if (vid_stream->picture.code_type == B_TYPE) {
  1584.  
  1585.     /* Reset prev. and current vectors to zero if mblock is intracoded. */
  1586.  
  1587.     if (vid_stream->mblock.mb_intra) {
  1588.       vid_stream->mblock.recon_right_for_prev = 0;
  1589.       vid_stream->mblock.recon_down_for_prev = 0;
  1590.       vid_stream->mblock.recon_right_back_prev = 0;
  1591.       vid_stream->mblock.recon_down_back_prev = 0;
  1592.     } else {
  1593.  
  1594.       /* If no forw vectors, current vectors equal prev. vectors. */
  1595.  
  1596.       if (!mb_motion_forw) {
  1597.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  1598.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  1599.       }
  1600.       /*
  1601.        * Otherwise compute forw. vectors. Reset prev vectors to new values.
  1602.        */
  1603.  
  1604.       else {
  1605.         ComputeForwVector(&recon_right_for, &recon_down_for);
  1606.       }
  1607.  
  1608.       /* If no back vectors, set back vectors to prev back vectors. */
  1609.  
  1610.       if (!mb_motion_back) {
  1611.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  1612.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  1613.       }
  1614.       /* Otherwise compute new vectors and reset prev. back vectors. */
  1615.  
  1616.       else {
  1617.     ComputeBackVector(&recon_right_back, &recon_down_back);
  1618.       }
  1619.  
  1620.       /*
  1621.        * Store vector existance flags in structure for possible skipped
  1622.        * macroblocks to follow.
  1623.        */
  1624.  
  1625.       vid_stream->mblock.bpict_past_forw = mb_motion_forw;
  1626.       vid_stream->mblock.bpict_past_back = mb_motion_back;
  1627.     }
  1628.   }
  1629.  
  1630.   /* For each possible block in macroblock. */
  1631. {
  1632.    {
  1633.       for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
  1634.     
  1635.     /* If block exists... */
  1636.     if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) {
  1637.       zero_block_flag = 0;
  1638.       ParseReconBlock(i);
  1639.     } else {
  1640.       zero_block_flag = 1;
  1641.     }
  1642.     
  1643.     /* If macroblock is intra coded... */
  1644.     if (vid_stream->mblock.mb_intra) {
  1645.       ReconIMBlock(vid_stream, i);
  1646.     } else if (mb_motion_forw && mb_motion_back) {
  1647.       ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1648.             recon_right_back, recon_down_back, zero_block_flag);
  1649.     } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) {
  1650.       ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for,
  1651.                zero_block_flag);
  1652.     } else if (mb_motion_back) {
  1653.       ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back,
  1654.                zero_block_flag);
  1655.     }
  1656.       }
  1657.     }
  1658.   }
  1659.  
  1660.   if ((ditherType == MBORDERED_DITHER) && (!no_dith_flag)) {
  1661.     if ((vid_stream->picture.code_type == 2) &&
  1662.     (vid_stream->mblock.cbp == 0) &&
  1663.     (!vid_stream->mblock.mb_intra)) {
  1664.  
  1665.       ditherFlags[vid_stream->mblock.mb_address] = 0;
  1666.     }
  1667.     else {
  1668.       ditherFlags[vid_stream->mblock.mb_address] = 1;
  1669.     }
  1670.   }
  1671.  
  1672.  
  1673.   /* If D Type picture, flush marker bit. */
  1674.   if (vid_stream->picture.code_type == 4)
  1675.     flush_bits(1);
  1676.  
  1677.   /* If macroblock was intracoded, set macroblock past intra address. */
  1678.   if (vid_stream->mblock.mb_intra)
  1679.     vid_stream->mblock.past_intra_addr =
  1680.       vid_stream->mblock.mb_address;
  1681.  
  1682.   *mbSizePtr += bitCountRead() - mbSizeCount;
  1683.   return PARSE_OK;
  1684. }
  1685.  
  1686.  
  1687.  
  1688. /*
  1689.  *--------------------------------------------------------------
  1690.  *
  1691.  * ReconIMBlock --
  1692.  *
  1693.  *    Reconstructs intra coded macroblock.
  1694.  *
  1695.  * Results:
  1696.  *    None.
  1697.  *
  1698.  * Side effects:
  1699.  *    None.
  1700.  *
  1701.  *--------------------------------------------------------------
  1702.  */
  1703.  
  1704. static void
  1705. ReconIMBlock(vid_stream, bnum)
  1706.   VidStream *vid_stream;
  1707.   int bnum;
  1708. {
  1709.   int mb_row, mb_col, row, col, row_size, rr;
  1710.   unsigned char *dest;
  1711.  
  1712.   /* Calculate macroblock row and column from address. */
  1713.  
  1714.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  1715.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  1716.  
  1717.  
  1718.   /* If block is luminance block... */
  1719.  
  1720.   if (bnum < 4) {
  1721.  
  1722.     /* Calculate row and col values for upper left pixel of block. */
  1723.  
  1724.     row = mb_row * 16;
  1725.     col = mb_col * 16;
  1726.     if (bnum > 1)
  1727.       row += 8;
  1728.     if (bnum % 2)
  1729.       col += 8;
  1730.  
  1731.     /* Set dest to luminance plane of current pict image. */
  1732.  
  1733.     dest = vid_stream->current->luminance;
  1734.  
  1735.     /* Establish row size. */
  1736.  
  1737.     row_size = vid_stream->mb_width * 16;
  1738.   }
  1739.   /* Otherwise if block is Cr block... */
  1740.  
  1741.   else if (bnum == 4) {
  1742.  
  1743.     /* Set dest to Cr plane of current pict image. */
  1744.  
  1745.     dest = vid_stream->current->Cr;
  1746.  
  1747.     /* Establish row size. */
  1748.  
  1749.     row_size = vid_stream->mb_width * 8;
  1750.  
  1751.     /* Calculate row,col for upper left pixel of block. */
  1752.  
  1753.     row = mb_row * 8;
  1754.     col = mb_col * 8;
  1755.   }
  1756.   /* Otherwise block is Cb block, and ... */
  1757.  
  1758.   else {
  1759.  
  1760.     /* Set dest to Cb plane of current pict image. */
  1761.  
  1762.     dest = vid_stream->current->Cb;
  1763.  
  1764.     /* Establish row size. */
  1765.  
  1766.     row_size = vid_stream->mb_width * 8;
  1767.  
  1768.     /* Calculate row,col for upper left pixel value of block. */
  1769.  
  1770.     row = mb_row * 8;
  1771.     col = mb_col * 8;
  1772.   }
  1773.  
  1774.   /*
  1775.    * For each pixel in block, set to cropped reconstructed value from inverse
  1776.    * dct.
  1777.    */
  1778.   {
  1779.     short *sp = &vid_stream->block.dct_recon[0][0];
  1780.     unsigned char *cm = cropTbl + MAX_NEG_CROP;
  1781.     dest += row * row_size + col;
  1782.     for (rr = 0; rr < 4; rr++, sp += 16, dest += row_size) {
  1783.       dest[0] = cm[sp[0]];
  1784.       assertCrop(sp[0]);
  1785.       dest[1] = cm[sp[1]];
  1786.       assertCrop(sp[1]);
  1787.       dest[2] = cm[sp[2]];
  1788.       assertCrop(sp[2]);
  1789.       dest[3] = cm[sp[3]];
  1790.       assertCrop(sp[3]);
  1791.       dest[4] = cm[sp[4]];
  1792.       assertCrop(sp[4]);
  1793.       dest[5] = cm[sp[5]];
  1794.       assertCrop(sp[5]);
  1795.       dest[6] = cm[sp[6]];
  1796.       assertCrop(sp[6]);
  1797.       dest[7] = cm[sp[7]];
  1798.       assertCrop(sp[7]);
  1799.  
  1800.       dest += row_size;
  1801.       dest[0] = cm[sp[8]];
  1802.       assertCrop(sp[8]);
  1803.       dest[1] = cm[sp[9]];
  1804.       assertCrop(sp[9]);
  1805.       dest[2] = cm[sp[10]];
  1806.       assertCrop(sp[10]);
  1807.       dest[3] = cm[sp[11]];
  1808.       assertCrop(sp[11]);
  1809.       dest[4] = cm[sp[12]];
  1810.       assertCrop(sp[12]);
  1811.       dest[5] = cm[sp[13]];
  1812.       assertCrop(sp[13]);
  1813.       dest[6] = cm[sp[14]];
  1814.       assertCrop(sp[14]);
  1815.       dest[7] = cm[sp[15]];
  1816.       assertCrop(sp[15]);
  1817.     }
  1818.   }
  1819. }
  1820.  
  1821.  
  1822.  
  1823. /*
  1824.  *--------------------------------------------------------------
  1825.  *
  1826.  * ReconPMBlock --
  1827.  *
  1828.  *    Reconstructs forward predicted macroblocks.
  1829.  *
  1830.  * Results:
  1831.  *      None.
  1832.  *
  1833.  * Side effects:
  1834.  *      None.
  1835.  *
  1836.  *--------------------------------------------------------------
  1837.  */
  1838.  
  1839. static void
  1840. ReconPMBlock(vid_stream, bnum, recon_right_for, recon_down_for, zflag)
  1841.   VidStream *vid_stream;
  1842.   int bnum, recon_right_for, recon_down_for, zflag;
  1843. {
  1844.   int mb_row, mb_col, row, col, row_size, rr;
  1845.   unsigned char *dest, *past;
  1846.   static int right_for, down_for, right_half_for, down_half_for;
  1847.   unsigned char *rindex1, *rindex2;
  1848.   unsigned char *index;
  1849.   short int *blockvals;
  1850.  
  1851.   /* Calculate macroblock row and column from address. */
  1852.  
  1853.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  1854.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  1855.  
  1856.   if (bnum < 4) {
  1857.  
  1858.     /* Calculate right_for, down_for motion vectors. */
  1859.  
  1860.     right_for = recon_right_for >> 1;
  1861.     down_for = recon_down_for >> 1;
  1862.     right_half_for = recon_right_for & 0x1;
  1863.     down_half_for = recon_down_for & 0x1;
  1864.  
  1865.     /* Set dest to luminance plane of current pict image. */
  1866.  
  1867.     dest = vid_stream->current->luminance;
  1868.  
  1869.     if (vid_stream->picture.code_type == B_TYPE) {
  1870.       if (vid_stream->past != NULL)
  1871.     past = vid_stream->past->luminance;
  1872.     } else {
  1873.  
  1874.       /* Set predicitive frame to current future frame. */
  1875.  
  1876.       if (vid_stream->future != NULL)
  1877.     past = vid_stream->future->luminance;
  1878.     }
  1879.  
  1880.     /* Establish row size. */
  1881.  
  1882.     row_size = vid_stream->mb_width << 4;
  1883.  
  1884.     /* Calculate row,col of upper left pixel in block. */
  1885.  
  1886.     row = mb_row << 4;
  1887.     col = mb_col << 4;
  1888.     if (bnum > 1)
  1889.       row += 8;
  1890.     if (bnum % 2)
  1891.       col += 8;
  1892.  
  1893.   }
  1894.   /* Otherwise, block is NOT luminance block, ... */
  1895.  
  1896.   else {
  1897.  
  1898.     /* Construct motion vectors. */
  1899.  
  1900.     recon_right_for /= 2;
  1901.     recon_down_for /= 2;
  1902.     right_for = recon_right_for >> 1;
  1903.     down_for = recon_down_for >> 1;
  1904.     right_half_for = recon_right_for & 0x1;
  1905.     down_half_for = recon_down_for & 0x1;
  1906.  
  1907.     /* Establish row size. */
  1908.  
  1909.     row_size = vid_stream->mb_width << 3;
  1910.  
  1911.     /* Calculate row,col of upper left pixel in block. */
  1912.  
  1913.     row = mb_row << 3;
  1914.     col = mb_col << 3;
  1915.  
  1916.     /* If block is Cr block... */
  1917.  
  1918.     if (bnum == 4) {
  1919.  
  1920.       /* Set dest to Cr plane of current pict image. */
  1921.  
  1922.       dest = vid_stream->current->Cr;
  1923.  
  1924.       if (vid_stream->picture.code_type == B_TYPE) {
  1925.  
  1926.     if (vid_stream->past != NULL)
  1927.       past = vid_stream->past->Cr;
  1928.       } else {
  1929.     if (vid_stream->future != NULL)
  1930.       past = vid_stream->future->Cr;
  1931.       }
  1932.     }
  1933.     /* Otherwise, block is Cb block... */
  1934.  
  1935.     else {
  1936.  
  1937.       /* Set dest to Cb plane of current pict image. */
  1938.  
  1939.       dest = vid_stream->current->Cb;
  1940.  
  1941.       if (vid_stream->picture.code_type == B_TYPE) {
  1942.     if (vid_stream->past != NULL)
  1943.       past = vid_stream->past->Cb;
  1944.       } else {
  1945.     if (vid_stream->future != NULL)
  1946.       past = vid_stream->future->Cb;
  1947.       }
  1948.     }
  1949.   }
  1950.  
  1951.  
  1952.     index = dest + (row * row_size) + col;
  1953.     rindex1 = past + (row + down_for) * row_size + col + right_for;
  1954.     
  1955.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  1956.     
  1957.     /*
  1958.      * Calculate predictive pixel value based on motion vectors and copy to
  1959.      * dest plane.
  1960.      */
  1961.     
  1962.     if ((!down_half_for) && (!right_half_for)) {
  1963.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  1964.       if (!zflag)
  1965.     for (rr = 0; rr < 4; rr++) {
  1966.       index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  1967.       index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  1968.       index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  1969.       index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  1970.       index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  1971.       index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  1972.       index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  1973.       index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  1974.       index += row_size;
  1975.       rindex1 += row_size;
  1976.       
  1977.       index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  1978.       index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  1979.       index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  1980.       index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  1981.       index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  1982.       index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  1983.       index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  1984.       index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  1985.       blockvals += 16;
  1986.       index += row_size;
  1987.       rindex1 += row_size;
  1988.     }
  1989.       else {
  1990.     if (right_for & 0x1) {
  1991.       /* No alignment, use bye copy */
  1992.       for (rr = 0; rr < 4; rr++) {
  1993.         index[0] = rindex1[0];
  1994.         index[1] = rindex1[1];
  1995.         index[2] = rindex1[2];
  1996.         index[3] = rindex1[3];
  1997.         index[4] = rindex1[4];
  1998.         index[5] = rindex1[5];
  1999.         index[6] = rindex1[6];
  2000.         index[7] = rindex1[7];
  2001.         index += row_size;
  2002.         rindex1 += row_size;
  2003.         
  2004.         index[0] = rindex1[0];
  2005.         index[1] = rindex1[1];
  2006.         index[2] = rindex1[2];
  2007.         index[3] = rindex1[3];
  2008.         index[4] = rindex1[4];
  2009.         index[5] = rindex1[5];
  2010.         index[6] = rindex1[6];
  2011.         index[7] = rindex1[7];
  2012.         index += row_size;
  2013.         rindex1 += row_size;
  2014.       }
  2015.     } else if (right_for & 0x2) {
  2016.       /* Half-word bit aligned, use 16 bit copy */
  2017.       short *src = (short *)rindex1;
  2018.       short *dest = (short *)index;
  2019.       row_size >>= 1;
  2020.       for (rr = 0; rr < 4; rr++) {
  2021.         dest[0] = src[0];
  2022.         dest[1] = src[1];
  2023.         dest[2] = src[2];
  2024.         dest[3] = src[3];
  2025.         dest += row_size;
  2026.         src += row_size;
  2027.         
  2028.         dest[0] = src[0];
  2029.         dest[1] = src[1];
  2030.         dest[2] = src[2];
  2031.         dest[3] = src[3];
  2032.         dest += row_size;
  2033.         src += row_size;
  2034.       }
  2035.     } else {
  2036.       /* Word aligned, use 32 bit copy */
  2037.       int *src = (int *)rindex1;
  2038.       int *dest = (int *)index;
  2039.       row_size >>= 2;
  2040.       for (rr = 0; rr < 4; rr++) {
  2041.         dest[0] = src[0];
  2042.         dest[1] = src[1];
  2043.         dest += row_size;
  2044.         src += row_size;
  2045.         
  2046.         dest[0] = src[0];
  2047.         dest[1] = src[1];
  2048.         dest += row_size;
  2049.         src += row_size;
  2050.       }
  2051.     }
  2052.       }
  2053.     } else {
  2054.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2055.       rindex2 = rindex1 + right_half_for + (down_half_for * row_size);
  2056.       if (!zflag)
  2057.     for (rr = 0; rr < 4; rr++) {
  2058.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]];
  2059.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]];
  2060.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]];
  2061.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]];
  2062.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]];
  2063.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]];
  2064.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]];
  2065.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]];
  2066.       index += row_size;
  2067.       rindex1 += row_size;
  2068.       rindex2 += row_size;
  2069.       
  2070.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]];
  2071.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]];
  2072.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]];
  2073.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]];
  2074.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]];
  2075.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]];
  2076.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]];
  2077.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]];
  2078.       blockvals += 16;
  2079.       index += row_size;
  2080.       rindex1 += row_size;
  2081.       rindex2 += row_size;
  2082.     }
  2083.       else
  2084.     for (rr = 0; rr < 4; rr++) {
  2085.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2086.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2087.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2088.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2089.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2090.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2091.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2092.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2093.       index += row_size;
  2094.       rindex1 += row_size;
  2095.       rindex2 += row_size;
  2096.       
  2097.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2098.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2099.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2100.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2101.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2102.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2103.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2104.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2105.       index += row_size;
  2106.       rindex1 += row_size;
  2107.       rindex2 += row_size;
  2108.     }
  2109.     }
  2110.  
  2111. }
  2112.  
  2113.  
  2114. /*
  2115.  *--------------------------------------------------------------
  2116.  *
  2117.  * ReconBMBlock --
  2118.  *
  2119.  *    Reconstructs back predicted macroblocks.
  2120.  *
  2121.  * Results:
  2122.  *      None.
  2123.  *
  2124.  * Side effects:
  2125.  *      None.
  2126.  *
  2127.  *--------------------------------------------------------------
  2128.  */
  2129.  
  2130. static void
  2131. ReconBMBlock(vid_stream, bnum, recon_right_back, recon_down_back, zflag)
  2132.   VidStream *vid_stream;
  2133.   int bnum, recon_right_back, recon_down_back, zflag;
  2134. {
  2135.   int mb_row, mb_col, row, col, row_size, rr;
  2136.   unsigned char *dest, *future;
  2137.   int right_back, down_back, right_half_back, down_half_back;
  2138.   unsigned char *rindex1, *rindex2;
  2139.   unsigned char *index;
  2140.   short int *blockvals;
  2141.  
  2142.   /* Calculate macroblock row and column from address. */
  2143.  
  2144.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2145.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2146.  
  2147.   /* If block is luminance block... */
  2148.  
  2149.   if (bnum < 4) {
  2150.  
  2151.     /* Calculate right_back, down_bakc motion vectors. */
  2152.  
  2153.     right_back = recon_right_back >> 1;
  2154.     down_back = recon_down_back >> 1;
  2155.     right_half_back = recon_right_back & 0x1;
  2156.     down_half_back = recon_down_back & 0x1;
  2157.  
  2158.     /* Set dest to luminance plane of current pict image. */
  2159.  
  2160.     dest = vid_stream->current->luminance;
  2161.  
  2162.     /*
  2163.      * If future frame exists, set future to luminance plane of future frame.
  2164.      */
  2165.  
  2166.     if (vid_stream->future != NULL)
  2167.       future = vid_stream->future->luminance;
  2168.  
  2169.     /* Establish row size. */
  2170.  
  2171.     row_size = vid_stream->mb_width << 4;
  2172.  
  2173.     /* Calculate row,col of upper left pixel in block. */
  2174.  
  2175.     row = mb_row << 4;
  2176.     col = mb_col << 4;
  2177.     if (bnum > 1)
  2178.       row += 8;
  2179.     if (bnum % 2)
  2180.       col += 8;
  2181.  
  2182.   }
  2183.   /* Otherwise, block is NOT luminance block, ... */
  2184.  
  2185.   else {
  2186.  
  2187.     /* Construct motion vectors. */
  2188.  
  2189.     recon_right_back /= 2;
  2190.     recon_down_back /= 2;
  2191.     right_back = recon_right_back >> 1;
  2192.     down_back = recon_down_back >> 1;
  2193.     right_half_back = recon_right_back & 0x1;
  2194.     down_half_back = recon_down_back & 0x1;
  2195.  
  2196.     /* Establish row size. */
  2197.  
  2198.     row_size = vid_stream->mb_width << 3;
  2199.  
  2200.     /* Calculate row,col of upper left pixel in block. */
  2201.  
  2202.     row = mb_row << 3;
  2203.     col = mb_col << 3;
  2204.  
  2205.     /* If block is Cr block... */
  2206.  
  2207.     if (bnum == 4) {
  2208.  
  2209.       /* Set dest to Cr plane of current pict image. */
  2210.  
  2211.       dest = vid_stream->current->Cr;
  2212.  
  2213.       /*
  2214.        * If future frame exists, set future to Cr plane of future image.
  2215.        */
  2216.  
  2217.       if (vid_stream->future != NULL)
  2218.     future = vid_stream->future->Cr;
  2219.     }
  2220.     /* Otherwise, block is Cb block... */
  2221.  
  2222.     else {
  2223.  
  2224.       /* Set dest to Cb plane of current pict image. */
  2225.  
  2226.       dest = vid_stream->current->Cb;
  2227.  
  2228.       /*
  2229.        * If future frame exists, set future to Cb plane of future frame.
  2230.        */
  2231.  
  2232.       if (vid_stream->future != NULL)
  2233.     future = vid_stream->future->Cb;
  2234.     }
  2235.   }
  2236.  
  2237.   /* For each pixel in block do... */
  2238.  
  2239.     index = dest + (row * row_size) + col;
  2240.     rindex1 = future + (row + down_back) * row_size + col + right_back;
  2241.  
  2242.     blockvals = &(vid_stream->block.dct_recon[0][0]);
  2243.  
  2244.     if ((!right_half_back) && (!down_half_back)) {
  2245.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2246.       if (!zflag)
  2247.     for (rr = 0; rr < 4; rr++) {
  2248.       index[0] = cm[(int) rindex1[0] + (int) blockvals[0]];
  2249.       index[1] = cm[(int) rindex1[1] + (int) blockvals[1]];
  2250.       index[2] = cm[(int) rindex1[2] + (int) blockvals[2]];
  2251.       index[3] = cm[(int) rindex1[3] + (int) blockvals[3]];
  2252.       index[4] = cm[(int) rindex1[4] + (int) blockvals[4]];
  2253.       index[5] = cm[(int) rindex1[5] + (int) blockvals[5]];
  2254.       index[6] = cm[(int) rindex1[6] + (int) blockvals[6]];
  2255.       index[7] = cm[(int) rindex1[7] + (int) blockvals[7]];
  2256.       index += row_size;
  2257.       rindex1 += row_size;
  2258.       
  2259.       index[0] = cm[(int) rindex1[0] + (int) blockvals[8]];
  2260.       index[1] = cm[(int) rindex1[1] + (int) blockvals[9]];
  2261.       index[2] = cm[(int) rindex1[2] + (int) blockvals[10]];
  2262.       index[3] = cm[(int) rindex1[3] + (int) blockvals[11]];
  2263.       index[4] = cm[(int) rindex1[4] + (int) blockvals[12]];
  2264.       index[5] = cm[(int) rindex1[5] + (int) blockvals[13]];
  2265.       index[6] = cm[(int) rindex1[6] + (int) blockvals[14]];
  2266.       index[7] = cm[(int) rindex1[7] + (int) blockvals[15]];
  2267.       blockvals += 16;
  2268.       index += row_size;
  2269.       rindex1 += row_size;
  2270.     }
  2271.       else {
  2272.     if (right_back & 0x1) {
  2273.       /* No alignment, use bye copy */
  2274.       for (rr = 0; rr < 4; rr++) {
  2275.         index[0] = rindex1[0];
  2276.         index[1] = rindex1[1];
  2277.         index[2] = rindex1[2];
  2278.         index[3] = rindex1[3];
  2279.         index[4] = rindex1[4];
  2280.         index[5] = rindex1[5];
  2281.         index[6] = rindex1[6];
  2282.         index[7] = rindex1[7];
  2283.         index += row_size;
  2284.         rindex1 += row_size;
  2285.         
  2286.         index[0] = rindex1[0];
  2287.         index[1] = rindex1[1];
  2288.         index[2] = rindex1[2];
  2289.         index[3] = rindex1[3];
  2290.         index[4] = rindex1[4];
  2291.         index[5] = rindex1[5];
  2292.         index[6] = rindex1[6];
  2293.         index[7] = rindex1[7];
  2294.         index += row_size;
  2295.         rindex1 += row_size;
  2296.       }
  2297.     } else if (right_back & 0x2) {
  2298.       /* Half-word bit aligned, use 16 bit copy */
  2299.       short *src = (short *)rindex1;
  2300.       short *dest = (short *)index;
  2301.       row_size >>= 1;
  2302.       for (rr = 0; rr < 4; rr++) {
  2303.         dest[0] = src[0];
  2304.         dest[1] = src[1];
  2305.         dest[2] = src[2];
  2306.         dest[3] = src[3];
  2307.         dest += row_size;
  2308.         src += row_size;
  2309.         
  2310.         dest[0] = src[0];
  2311.         dest[1] = src[1];
  2312.         dest[2] = src[2];
  2313.         dest[3] = src[3];
  2314.         dest += row_size;
  2315.         src += row_size;
  2316.       }
  2317.     } else {
  2318.       /* Word aligned, use 32 bit copy */
  2319.       int *src = (int *)rindex1;
  2320.       int *dest = (int *)index;
  2321.       row_size >>= 2;
  2322.       for (rr = 0; rr < 4; rr++) {
  2323.         dest[0] = src[0];
  2324.         dest[1] = src[1];
  2325.         dest += row_size;
  2326.         src += row_size;
  2327.         
  2328.         dest[0] = src[0];
  2329.         dest[1] = src[1];
  2330.         dest += row_size;
  2331.         src += row_size;
  2332.       }
  2333.     }
  2334.       }
  2335.     } else {
  2336.       unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2337.       rindex2 = rindex1 + right_half_back + (down_half_back * row_size);
  2338.       if (!zflag)
  2339.     for (rr = 0; rr < 4; rr++) {
  2340.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]];
  2341.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]];
  2342.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]];
  2343.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]];
  2344.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]];
  2345.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]];
  2346.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]];
  2347.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]];
  2348.       index += row_size;
  2349.       rindex1 += row_size;
  2350.       rindex2 += row_size;
  2351.       
  2352.       index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]];
  2353.       index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]];
  2354.       index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]];
  2355.       index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]];
  2356.       index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]];
  2357.       index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]];
  2358.       index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]];
  2359.       index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]];
  2360.       blockvals += 16;
  2361.       index += row_size;
  2362.       rindex1 += row_size;
  2363.       rindex2 += row_size;
  2364.     }
  2365.       else
  2366.     for (rr = 0; rr < 4; rr++) {
  2367.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2368.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2369.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2370.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2371.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2372.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2373.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2374.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2375.       index += row_size;
  2376.       rindex1 += row_size;
  2377.       rindex2 += row_size;
  2378.       
  2379.       index[0] = (int) (rindex1[0] + rindex2[0]) >> 1;
  2380.       index[1] = (int) (rindex1[1] + rindex2[1]) >> 1;
  2381.       index[2] = (int) (rindex1[2] + rindex2[2]) >> 1;
  2382.       index[3] = (int) (rindex1[3] + rindex2[3]) >> 1;
  2383.       index[4] = (int) (rindex1[4] + rindex2[4]) >> 1;
  2384.       index[5] = (int) (rindex1[5] + rindex2[5]) >> 1;
  2385.       index[6] = (int) (rindex1[6] + rindex2[6]) >> 1;
  2386.       index[7] = (int) (rindex1[7] + rindex2[7]) >> 1;
  2387.       index += row_size;
  2388.       rindex1 += row_size;
  2389.       rindex2 += row_size;
  2390.     }
  2391.     }
  2392.  
  2393. }
  2394.  
  2395.  
  2396. /*
  2397.  *--------------------------------------------------------------
  2398.  *
  2399.  * ReconBiMBlock --
  2400.  *
  2401.  *    Reconstructs bidirectionally predicted macroblocks.
  2402.  *
  2403.  * Results:
  2404.  *      None.
  2405.  *
  2406.  * Side effects:
  2407.  *      None.
  2408.  *
  2409.  *--------------------------------------------------------------
  2410.  */
  2411.  
  2412. static void
  2413. ReconBiMBlock(vid_stream, bnum, recon_right_for, recon_down_for,
  2414.           recon_right_back, recon_down_back, zflag)
  2415.   VidStream *vid_stream;
  2416.   int bnum, recon_right_for, recon_down_for, recon_right_back, recon_down_back;
  2417.   int zflag;
  2418. {
  2419.   int mb_row, mb_col, row, col, row_size, rr;
  2420.   unsigned char *dest, *past, *future;
  2421.   int right_for, down_for, right_half_for, down_half_for;
  2422.   int right_back, down_back, right_half_back, down_half_back;
  2423.   unsigned char *index, *rindex1, *bindex1;
  2424.   short int *blockvals;
  2425.   int forw_row_start, back_row_start, forw_col_start, back_col_start;
  2426.  
  2427.   /* Calculate macroblock row and column from address. */
  2428.  
  2429.   mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width;
  2430.   mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width;
  2431.  
  2432.   /* If block is luminance block... */
  2433.  
  2434.   if (bnum < 4) {
  2435.  
  2436.     /*
  2437.      * Calculate right_for, down_for, right_half_for, down_half_for,
  2438.      * right_back, down_bakc, right_half_back, and down_half_back, motion
  2439.      * vectors.
  2440.      */
  2441.  
  2442.     right_for = recon_right_for >> 1;
  2443.     down_for = recon_down_for >> 1;
  2444.     right_half_for = recon_right_for & 0x1;
  2445.     down_half_for = recon_down_for & 0x1;
  2446.  
  2447.     right_back = recon_right_back >> 1;
  2448.     down_back = recon_down_back >> 1;
  2449.     right_half_back = recon_right_back & 0x1;
  2450.     down_half_back = recon_down_back & 0x1;
  2451.  
  2452.     /* Set dest to luminance plane of current pict image. */
  2453.  
  2454.     dest = vid_stream->current->luminance;
  2455.  
  2456.     /* If past frame exists, set past to luminance plane of past frame. */
  2457.  
  2458.     if (vid_stream->past != NULL)
  2459.       past = vid_stream->past->luminance;
  2460.  
  2461.     /*
  2462.      * If future frame exists, set future to luminance plane of future frame.
  2463.      */
  2464.  
  2465.     if (vid_stream->future != NULL)
  2466.       future = vid_stream->future->luminance;
  2467.  
  2468.     /* Establish row size. */
  2469.  
  2470.     row_size = (vid_stream->mb_width << 4);
  2471.  
  2472.     /* Calculate row,col of upper left pixel in block. */
  2473.  
  2474.     row = (mb_row << 4);
  2475.     col = (mb_col << 4);
  2476.     if (bnum > 1)
  2477.       row += 8;
  2478.     if (bnum & 0x01)
  2479.       col += 8;
  2480.  
  2481.     forw_col_start = col + right_for;
  2482.     forw_row_start = row + down_for;
  2483.  
  2484.     back_col_start = col + right_back;
  2485.     back_row_start = row + down_back;
  2486.  
  2487.   }
  2488.   /* Otherwise, block is NOT luminance block, ... */
  2489.  
  2490.   else {
  2491.  
  2492.     /* Construct motion vectors. */
  2493.  
  2494.     recon_right_for /= 2;
  2495.     recon_down_for /= 2;
  2496.     right_for = recon_right_for >> 1;
  2497.     down_for = recon_down_for >> 1;
  2498.     right_half_for = recon_right_for & 0x1;
  2499.     down_half_for = recon_down_for & 0x1;
  2500.  
  2501.     recon_right_back /= 2;
  2502.     recon_down_back /= 2;
  2503.     right_back = recon_right_back >> 1;
  2504.     down_back = recon_down_back >> 1;
  2505.     right_half_back = recon_right_back & 0x1;
  2506.     down_half_back = recon_down_back & 0x1;
  2507.  
  2508.     /* Establish row size. */
  2509.  
  2510.     row_size = (vid_stream->mb_width << 3);
  2511.  
  2512.     /* Calculate row,col of upper left pixel in block. */
  2513.  
  2514.     row = (mb_row << 3);
  2515.     col = (mb_col << 3);
  2516.  
  2517.     forw_col_start = col + right_for;
  2518.     forw_row_start = row + down_for;
  2519.  
  2520.     back_col_start = col + right_back;
  2521.     back_row_start = row + down_back;
  2522.  
  2523.     /* If block is Cr block... */
  2524.  
  2525.     if (bnum == 4) {
  2526.  
  2527.       /* Set dest to Cr plane of current pict image. */
  2528.  
  2529.       dest = vid_stream->current->Cr;
  2530.  
  2531.       /* If past frame exists, set past to Cr plane of past image. */
  2532.  
  2533.       if (vid_stream->past != NULL)
  2534.     past = vid_stream->past->Cr;
  2535.  
  2536.       /*
  2537.        * If future frame exists, set future to Cr plane of future image.
  2538.        */
  2539.  
  2540.       if (vid_stream->future != NULL)
  2541.     future = vid_stream->future->Cr;
  2542.     }
  2543.     /* Otherwise, block is Cb block... */
  2544.  
  2545.     else {
  2546.  
  2547.       /* Set dest to Cb plane of current pict image. */
  2548.  
  2549.       dest = vid_stream->current->Cb;
  2550.  
  2551.       /* If past frame exists, set past to Cb plane of past frame. */
  2552.  
  2553.       if (vid_stream->past != NULL)
  2554.     past = vid_stream->past->Cb;
  2555.  
  2556.       /*
  2557.        * If future frame exists, set future to Cb plane of future frame.
  2558.        */
  2559.  
  2560.       if (vid_stream->future != NULL)
  2561.     future = vid_stream->future->Cb;
  2562.     }
  2563.   }
  2564.  
  2565.   /* For each pixel in block... */
  2566.  
  2567.   index = dest + (row * row_size) + col;
  2568.  
  2569.     rindex1 = past + forw_row_start  * row_size + forw_col_start;
  2570.  
  2571.     bindex1 = future + back_row_start * row_size + back_col_start;
  2572.  
  2573.   blockvals = (short int *) &(vid_stream->block.dct_recon[0][0]);
  2574.  
  2575.   {
  2576.   unsigned char *cm = cropTbl + MAX_NEG_CROP;
  2577.   if (!zflag)
  2578.     for (rr = 0; rr < 4; rr++) {
  2579.       index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[0]];
  2580.       index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[1]];
  2581.       index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[2]];
  2582.       index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[3]];
  2583.       index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[4]];
  2584.       index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[5]];
  2585.       index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[6]];
  2586.       index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[7]];
  2587.       index += row_size;
  2588.       rindex1 += row_size;
  2589.       bindex1 += row_size;
  2590.  
  2591.       index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[8]];
  2592.       index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[9]];
  2593.       index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[10]];
  2594.       index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[11]];
  2595.       index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[12]];
  2596.       index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[13]];
  2597.       index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[14]];
  2598.       index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[15]];
  2599.       blockvals += 16;
  2600.       index += row_size;
  2601.       rindex1 += row_size;
  2602.       bindex1 += row_size;
  2603.     }
  2604.  
  2605.   else
  2606.     for (rr = 0; rr < 4; rr++) {
  2607.       index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
  2608.       index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
  2609.       index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
  2610.       index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
  2611.       index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
  2612.       index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
  2613.       index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
  2614.       index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
  2615.       index += row_size;
  2616.       rindex1 += row_size;
  2617.       bindex1 += row_size;
  2618.  
  2619.       index[0] = (int) (rindex1[0] + bindex1[0]) >> 1;
  2620.       index[1] = (int) (rindex1[1] + bindex1[1]) >> 1;
  2621.       index[2] = (int) (rindex1[2] + bindex1[2]) >> 1;
  2622.       index[3] = (int) (rindex1[3] + bindex1[3]) >> 1;
  2623.       index[4] = (int) (rindex1[4] + bindex1[4]) >> 1;
  2624.       index[5] = (int) (rindex1[5] + bindex1[5]) >> 1;
  2625.       index[6] = (int) (rindex1[6] + bindex1[6]) >> 1;
  2626.       index[7] = (int) (rindex1[7] + bindex1[7]) >> 1;
  2627.       index += row_size;
  2628.       rindex1 += row_size;
  2629.       bindex1 += row_size;
  2630.     }
  2631.   }
  2632. }
  2633.  
  2634. /*
  2635.  *--------------------------------------------------------------
  2636.  *
  2637.  * ProcessSkippedPFrameMBlocks --
  2638.  *
  2639.  *    Processes skipped macroblocks in P frames.
  2640.  *
  2641.  * Results:
  2642.  *    Calculates pixel values for luminance, Cr, and Cb planes
  2643.  *      in current pict image for skipped macroblocks.
  2644.  *
  2645.  * Side effects:
  2646.  *    Pixel values in pict image changed.
  2647.  *
  2648.  *--------------------------------------------------------------
  2649.  */
  2650.  
  2651. static void
  2652. ProcessSkippedPFrameMBlocks(vid_stream)
  2653.   VidStream *vid_stream;
  2654. {
  2655.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  2656.   int addr, row_incr, half_row_incr, crow, ccol;
  2657.   int *dest, *src, *dest1, *src1;
  2658.  
  2659.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  2660.  
  2661.   row_size = vid_stream->mb_width << 4;
  2662.   half_row = (row_size >> 1);
  2663.   row_incr = row_size >> 2;
  2664.   half_row_incr = half_row >> 2;
  2665.  
  2666.   /* For each skipped macroblock, do... */
  2667.  
  2668.   for (addr = vid_stream->mblock.past_mb_addr + 1;
  2669.        addr < vid_stream->mblock.mb_address; addr++) {
  2670.  
  2671.     /* Calculate macroblock row and col. */
  2672.  
  2673.     mb_row = addr / vid_stream->mb_width;
  2674.     mb_col = addr % vid_stream->mb_width;
  2675.  
  2676.     /* Calculate upper left pixel row,col for luminance plane. */
  2677.  
  2678.     row = mb_row << 4;
  2679.     col = mb_col << 4;
  2680.  
  2681.  
  2682.     /* For each row in macroblock luminance plane... */
  2683.  
  2684.     dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  2685.     src = (int *)(vid_stream->future->luminance + (row * row_size) + col);
  2686.  
  2687.     for (rr = 0; rr < 8; rr++) {
  2688.  
  2689.       /* Copy pixel values from last I or P picture. */
  2690.  
  2691.       dest[0] = src[0];
  2692.       dest[1] = src[1];
  2693.       dest[2] = src[2];
  2694.       dest[3] = src[3];
  2695.       dest += row_incr;
  2696.       src += row_incr;
  2697.  
  2698.       dest[0] = src[0];
  2699.       dest[1] = src[1];
  2700.       dest[2] = src[2];
  2701.       dest[3] = src[3];
  2702.       dest += row_incr;
  2703.       src += row_incr;
  2704.     }
  2705.  
  2706.     /*
  2707.      * Divide row,col to get upper left pixel of macroblock in Cr and Cb
  2708.      * planes.
  2709.      */
  2710.  
  2711.     crow = row >> 1;
  2712.     ccol = col >> 1;
  2713.  
  2714.     /* For each row in Cr, and Cb planes... */
  2715.  
  2716.     dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  2717.     src = (int *)(vid_stream->future->Cr + (crow * half_row) + ccol);
  2718.     dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  2719.     src1 = (int *)(vid_stream->future->Cb + (crow * half_row) + ccol);
  2720.  
  2721.     for (rr = 0; rr < 4; rr++) {
  2722.  
  2723.       /* Copy pixel values from last I or P picture. */
  2724.  
  2725.       dest[0] = src[0];
  2726.       dest[1] = src[1];
  2727.  
  2728.       dest1[0] = src1[0];
  2729.       dest1[1] = src1[1];
  2730.  
  2731.       dest += half_row_incr;
  2732.       src += half_row_incr;
  2733.       dest1 += half_row_incr;
  2734.       src1 += half_row_incr;
  2735.  
  2736.       dest[0] = src[0];
  2737.       dest[1] = src[1];
  2738.  
  2739.       dest1[0] = src1[0];
  2740.       dest1[1] = src1[1];
  2741.  
  2742.       dest += half_row_incr;
  2743.       src += half_row_incr;
  2744.       dest1 += half_row_incr;
  2745.       src1 += half_row_incr;
  2746.     }
  2747.  
  2748.     if (ditherType == MBORDERED_DITHER) {
  2749.     /*
  2750.       MBOrderedDitherDisplayCopy(vid_stream, addr,
  2751.                  1, 0, 0, 0, 0, 0,
  2752.                  vid_stream->future->display,
  2753.                  (unsigned char *) NULL);
  2754.     */
  2755.       ditherFlags[addr] = 0;
  2756.     }
  2757.   }
  2758.  
  2759.   vid_stream->mblock.recon_right_for_prev = 0;
  2760.   vid_stream->mblock.recon_down_for_prev = 0;
  2761. }
  2762.  
  2763.  
  2764.  
  2765.  
  2766. /*
  2767.  *--------------------------------------------------------------
  2768.  *
  2769.  * ProcessSkippedBFrameMBlocks --
  2770.  *
  2771.  *    Processes skipped macroblocks in B frames.
  2772.  *
  2773.  * Results:
  2774.  *    Calculates pixel values for luminance, Cr, and Cb planes
  2775.  *      in current pict image for skipped macroblocks.
  2776.  *
  2777.  * Side effects:
  2778.  *    Pixel values in pict image changed.
  2779.  *
  2780.  *--------------------------------------------------------------
  2781.  */
  2782.  
  2783. static void
  2784. ProcessSkippedBFrameMBlocks(vid_stream)
  2785.   VidStream *vid_stream;
  2786. {
  2787.   int row_size, half_row, mb_row, mb_col, row, col, rr;
  2788.   int right_half_for, down_half_for, c_right_half_for, c_down_half_for;
  2789.   int right_half_back, down_half_back, c_right_half_back, c_down_half_back;
  2790.   int addr, right_for, down_for;
  2791.   int recon_right_for, recon_down_for;
  2792.   int recon_right_back, recon_down_back;
  2793.   int right_back, down_back;
  2794.   int c_right_for, c_down_for;
  2795.   int c_right_back, c_down_back;
  2796.   unsigned char forw_lum[256];
  2797.   unsigned char forw_cr[64], forw_cb[64];
  2798.   unsigned char back_lum[256], back_cr[64], back_cb[64];
  2799.   int row_incr, half_row_incr;
  2800.   int ccol, crow;
  2801.  
  2802.   /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
  2803.  
  2804.   row_size = vid_stream->mb_width << 4;
  2805.   half_row = (row_size >> 1);
  2806.   row_incr = row_size >> 2;
  2807.   half_row_incr =  half_row >> 2;
  2808.  
  2809.   /* Establish motion vector codes based on full pixel flag. */
  2810.  
  2811.   if (vid_stream->picture.full_pel_forw_vector) {
  2812.     recon_right_for = vid_stream->mblock.recon_right_for_prev << 1;
  2813.     recon_down_for = vid_stream->mblock.recon_down_for_prev << 1;
  2814.   } else {
  2815.     recon_right_for = vid_stream->mblock.recon_right_for_prev;
  2816.     recon_down_for = vid_stream->mblock.recon_down_for_prev;
  2817.   }
  2818.  
  2819.   if (vid_stream->picture.full_pel_back_vector) {
  2820.     recon_right_back = vid_stream->mblock.recon_right_back_prev << 1;
  2821.     recon_down_back = vid_stream->mblock.recon_down_back_prev << 1;
  2822.   } else {
  2823.     recon_right_back = vid_stream->mblock.recon_right_back_prev;
  2824.     recon_down_back = vid_stream->mblock.recon_down_back_prev;
  2825.   }
  2826.  
  2827.  
  2828.   /* Calculate motion vectors. */
  2829.   
  2830.   if (vid_stream->mblock.bpict_past_forw) {
  2831.     right_for = recon_right_for >> 1;
  2832.     down_for = recon_down_for >> 1;
  2833.     right_half_for = recon_right_for & 0x1;
  2834.     down_half_for = recon_down_for & 0x1;
  2835.     
  2836.     recon_right_for /= 2;
  2837.     recon_down_for /= 2;
  2838.     c_right_for = recon_right_for >> 1;
  2839.     c_down_for = recon_down_for >> 1;
  2840.     c_right_half_for = recon_right_for & 0x1;
  2841.     c_down_half_for = recon_down_for & 0x1;
  2842.     
  2843.   }
  2844.   if (vid_stream->mblock.bpict_past_back) {
  2845.     right_back = recon_right_back >> 1;
  2846.     down_back = recon_down_back >> 1;
  2847.     right_half_back = recon_right_back & 0x1;
  2848.     down_half_back = recon_down_back & 0x1;
  2849.     
  2850.     recon_right_back /= 2;
  2851.     recon_down_back /= 2;
  2852.     c_right_back = recon_right_back >> 1;
  2853.     c_down_back = recon_down_back >> 1;
  2854.     c_right_half_back = recon_right_back & 0x1;
  2855.     c_down_half_back = recon_down_back & 0x1;
  2856.     
  2857.   }
  2858.   /* For each skipped macroblock, do... */
  2859.   
  2860.   for (addr = vid_stream->mblock.past_mb_addr + 1;
  2861.        addr < vid_stream->mblock.mb_address; addr++) {
  2862.     
  2863.     /* Calculate macroblock row and col. */
  2864.     
  2865.     mb_row = addr / vid_stream->mb_width;
  2866.     mb_col = addr % vid_stream->mb_width;
  2867.     
  2868.     /* Calculate upper left pixel row,col for luminance plane. */
  2869.     
  2870.     row = mb_row << 4;
  2871.     col = mb_col << 4;
  2872.     crow = row / 2;
  2873.     ccol = col / 2;
  2874.     
  2875.     /* If forward predicted, calculate prediction values. */
  2876.     
  2877.     if (vid_stream->mblock.bpict_past_forw) {
  2878.       
  2879.       ReconSkippedBlock(vid_stream->past->luminance, forw_lum,
  2880.             row, col, row_size, right_for, down_for,
  2881.             right_half_for, down_half_for, 16);
  2882.       ReconSkippedBlock(vid_stream->past->Cr, forw_cr, crow,
  2883.             ccol, half_row,
  2884.             c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
  2885.       ReconSkippedBlock(vid_stream->past->Cb, forw_cb, crow,
  2886.             ccol, half_row,
  2887.             c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8);
  2888.     }
  2889.     /* If back predicted, calculate prediction values. */
  2890.     
  2891.     if (vid_stream->mblock.bpict_past_back) {
  2892.       ReconSkippedBlock(vid_stream->future->luminance, back_lum,
  2893.             row, col, row_size, right_back, down_back,
  2894.             right_half_back, down_half_back, 16);
  2895.       ReconSkippedBlock(vid_stream->future->Cr, back_cr, crow,
  2896.             ccol, half_row,
  2897.             c_right_back, c_down_back,
  2898.             c_right_half_back, c_down_half_back, 8);
  2899.       ReconSkippedBlock(vid_stream->future->Cb, back_cb, crow,
  2900.             ccol, half_row,
  2901.             c_right_back, c_down_back,
  2902.             c_right_half_back, c_down_half_back, 8);
  2903.     }
  2904.     if (vid_stream->mblock.bpict_past_forw &&
  2905.     !vid_stream->mblock.bpict_past_back) {
  2906.       
  2907.       int *dest, *dest1;
  2908.       int *src, *src1;
  2909.       dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  2910.       src = (int *)forw_lum;
  2911.       
  2912.       for (rr = 0; rr < 16; rr++) {
  2913.     
  2914.     /* memcpy(dest, forw_lum+(rr<<4), 16);  */
  2915.     dest[0] = src[0];
  2916.     dest[1] = src[1];
  2917.     dest[2] = src[2];
  2918.     dest[3] = src[3];
  2919.     dest += row_incr;
  2920.     src += 4;
  2921.       }
  2922.       
  2923.       dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  2924.       dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  2925.       src = (int *)forw_cr;
  2926.       src1 = (int *)forw_cb;
  2927.       
  2928.       for (rr = 0; rr < 8; rr++) {
  2929.     /*
  2930.      * memcpy(dest, forw_cr+(rr<<3), 8); memcpy(dest1, forw_cb+(rr<<3),
  2931.      * 8);
  2932.      */
  2933.     
  2934.     dest[0] = src[0];
  2935.     dest[1] = src[1];
  2936.     
  2937.     dest1[0] = src1[0];
  2938.     dest1[1] = src1[1];
  2939.     
  2940.     dest += half_row_incr;
  2941.     dest1 += half_row_incr;
  2942.     src += 2;
  2943.     src1 += 2;
  2944.       }
  2945.     } else if (vid_stream->mblock.bpict_past_back &&
  2946.            !vid_stream->mblock.bpict_past_forw) {
  2947.       
  2948.       int *src, *src1;
  2949.       int *dest, *dest1;
  2950.       dest = (int *)(vid_stream->current->luminance + (row * row_size) + col);
  2951.       src = (int *)back_lum;
  2952.       
  2953.       for (rr = 0; rr < 16; rr++) {
  2954.     dest[0] = src[0];
  2955.     dest[1] = src[1];
  2956.     dest[2] = src[2];
  2957.     dest[3] = src[3];
  2958.     dest += row_incr;
  2959.     src += 4;
  2960.       }
  2961.       
  2962.       
  2963.       dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol);
  2964.       dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol);
  2965.       src = (int *)back_cr;
  2966.       src1 = (int *)back_cb;
  2967.       
  2968.       for (rr = 0; rr < 8; rr++) {
  2969.     /*
  2970.      * memcpy(dest, back_cr+(rr<<3), 8); memcpy(dest1, back_cb+(rr<<3),
  2971.      * 8);
  2972.      */
  2973.     
  2974.     dest[0] = src[0];
  2975.     dest[1] = src[1];
  2976.     
  2977.     dest1[0] = src1[0];
  2978.     dest1[1] = src1[1];
  2979.     
  2980.     dest += half_row_incr;
  2981.     dest1 += half_row_incr;
  2982.     src += 2;
  2983.     src1 += 2;
  2984.       }
  2985.     } else {
  2986.       
  2987.       unsigned char *src1, *src2, *src1a, *src2a;
  2988.       unsigned char *dest, *dest1;
  2989.       dest = vid_stream->current->luminance + (row * row_size) + col;
  2990.       src1 = forw_lum;
  2991.       src2 = back_lum;
  2992.       
  2993.       for (rr = 0; rr < 16; rr++) {
  2994.     dest[0] = (int) (src1[0] + src2[0]) >> 1;
  2995.     dest[1] = (int) (src1[1] + src2[1]) >> 1;
  2996.     dest[2] = (int) (src1[2] + src2[2]) >> 1;
  2997.     dest[3] = (int) (src1[3] + src2[3]) >> 1;
  2998.     dest[4] = (int) (src1[4] + src2[4]) >> 1;
  2999.     dest[5] = (int) (src1[5] + src2[5]) >> 1;
  3000.     dest[6] = (int) (src1[6] + src2[6]) >> 1;
  3001.     dest[7] = (int) (src1[7] + src2[7]) >> 1;
  3002.     dest[8] = (int) (src1[8] + src2[8]) >> 1;
  3003.     dest[9] = (int) (src1[9] + src2[9]) >> 1;
  3004.     dest[10] = (int) (src1[10] + src2[10]) >> 1;
  3005.     dest[11] = (int) (src1[11] + src2[11]) >> 1;
  3006.     dest[12] = (int) (src1[12] + src2[12]) >> 1;
  3007.     dest[13] = (int) (src1[13] + src2[13]) >> 1;
  3008.     dest[14] = (int) (src1[14] + src2[14]) >> 1;
  3009.     dest[15] = (int) (src1[15] + src2[15]) >> 1;
  3010.     dest += row_size;
  3011.     src1 += 16;
  3012.     src2 += 16;
  3013.       }
  3014.       
  3015.       
  3016.       dest = vid_stream->current->Cr + (crow * half_row) + ccol;
  3017.       dest1 = vid_stream->current->Cb + (crow * half_row) + ccol;
  3018.       src1 = forw_cr;
  3019.       src2 = back_cr;
  3020.       src1a = forw_cb;
  3021.       src2a = back_cb;
  3022.       
  3023.       for (rr = 0; rr < 8; rr++) {
  3024.     dest[0] = (int) (src1[0] + src2[0]) >> 1;
  3025.     dest[1] = (int) (src1[1] + src2[1]) >> 1;
  3026.     dest[2] = (int) (src1[2] + src2[2]) >> 1;
  3027.     dest[3] = (int) (src1[3] + src2[3]) >> 1;
  3028.     dest[4] = (int) (src1[4] + src2[4]) >> 1;
  3029.     dest[5] = (int) (src1[5] + src2[5]) >> 1;
  3030.     dest[6] = (int) (src1[6] + src2[6]) >> 1;
  3031.     dest[7] = (int) (src1[7] + src2[7]) >> 1;
  3032.     dest += half_row;
  3033.     src1 += 8;
  3034.     src2 += 8;
  3035.     
  3036.     dest1[0] = (int) (src1a[0] + src2a[0]) >> 1;
  3037.     dest1[1] = (int) (src1a[1] + src2a[1]) >> 1;
  3038.     dest1[2] = (int) (src1a[2] + src2a[2]) >> 1;
  3039.     dest1[3] = (int) (src1a[3] + src2a[3]) >> 1;
  3040.     dest1[4] = (int) (src1a[4] + src2a[4]) >> 1;
  3041.     dest1[5] = (int) (src1a[5] + src2a[5]) >> 1;
  3042.     dest1[6] = (int) (src1a[6] + src2a[6]) >> 1;
  3043.     dest1[7] = (int) (src1a[7] + src2a[7]) >> 1;
  3044.     dest1 += half_row;
  3045.     src1a += 8;
  3046.     src2a += 8;
  3047.       }
  3048.     }
  3049.     
  3050.     if (ditherType == MBORDERED_DITHER) {
  3051.       ditherFlags[addr] = 1;
  3052.     }
  3053.   }
  3054. }
  3055.  
  3056.  
  3057.  
  3058.  
  3059. /*
  3060.  *--------------------------------------------------------------
  3061.  *
  3062.  * ReconSkippedBlock --
  3063.  *
  3064.  *    Reconstructs predictive block for skipped macroblocks
  3065.  *      in B Frames.
  3066.  *
  3067.  * Results:
  3068.  *    No return values.
  3069.  *
  3070.  * Side effects:
  3071.  *    None.
  3072.  *
  3073.  *--------------------------------------------------------------
  3074.  */
  3075.  
  3076. static void
  3077. ReconSkippedBlock(source, dest, row, col, row_size,
  3078.           right, down, right_half, down_half, width)
  3079.   unsigned char *source;
  3080.   unsigned char *dest;
  3081.   int row, col, row_size, right, down, right_half, down_half, width;
  3082. {
  3083.   int rr;
  3084.   unsigned char *source2;
  3085.  
  3086.   source += ((row + down) * row_size) + col + right;
  3087.  
  3088.   if (width == 16) {
  3089.     if ((!right_half) && (!down_half)) {
  3090.     if (right & 0x1) {
  3091.       /* No alignment, use bye copy */
  3092.       for (rr = 0; rr < 16; rr++) {
  3093.         dest[0] = source[0];
  3094.         dest[1] = source[1];
  3095.         dest[2] = source[2];
  3096.         dest[3] = source[3];
  3097.         dest[4] = source[4];
  3098.         dest[5] = source[5];
  3099.         dest[6] = source[6];
  3100.         dest[7] = source[7];
  3101.         dest[8] = source[8];
  3102.         dest[9] = source[9];
  3103.         dest[10] = source[10];
  3104.         dest[11] = source[11];
  3105.         dest[12] = source[12];
  3106.         dest[13] = source[13];
  3107.         dest[14] = source[14];
  3108.         dest[15] = source[15];
  3109.         dest += 16;
  3110.         source += row_size;
  3111.       }
  3112.     } else if (right & 0x2) {
  3113.       /* Half-word bit aligned, use 16 bit copy */
  3114.       short *src = (short *)source;
  3115.       short *d = (short *)dest;
  3116.       row_size >>= 1;
  3117.       for (rr = 0; rr < 16; rr++) {
  3118.         d[0] = src[0];
  3119.         d[1] = src[1];
  3120.         d[2] = src[2];
  3121.         d[3] = src[3];
  3122.         d[4] = src[4];
  3123.         d[5] = src[5];
  3124.         d[6] = src[6];
  3125.         d[7] = src[7];
  3126.         d += 8;
  3127.         src += row_size;
  3128.       }
  3129.     } else {
  3130.       /* Word aligned, use 32 bit copy */
  3131.       int *src = (int *)source;
  3132.       int *d = (int *)dest;
  3133.       row_size >>= 2;
  3134.       for (rr = 0; rr < 16; rr++) {
  3135.         d[0] = src[0];
  3136.         d[1] = src[1];
  3137.         d[2] = src[2];
  3138.         d[3] = src[3];
  3139.         d += 4;
  3140.         src += row_size;
  3141.       }
  3142.     }
  3143.     } else {
  3144.       source2 = source + right_half + (row_size * down_half);
  3145.       for (rr = 0; rr < width; rr++) {
  3146.     dest[0] = (int) (source[0] + source2[0]) >> 1;
  3147.     dest[1] = (int) (source[1] + source2[1]) >> 1;
  3148.     dest[2] = (int) (source[2] + source2[2]) >> 1;
  3149.     dest[3] = (int) (source[3] + source2[3]) >> 1;
  3150.     dest[4] = (int) (source[4] + source2[4]) >> 1;
  3151.     dest[5] = (int) (source[5] + source2[5]) >> 1;
  3152.     dest[6] = (int) (source[6] + source2[6]) >> 1;
  3153.     dest[7] = (int) (source[7] + source2[7]) >> 1;
  3154.     dest[8] = (int) (source[8] + source2[8]) >> 1;
  3155.     dest[9] = (int) (source[9] + source2[9]) >> 1;
  3156.     dest[10] = (int) (source[10] + source2[10]) >> 1;
  3157.     dest[11] = (int) (source[11] + source2[11]) >> 1;
  3158.     dest[12] = (int) (source[12] + source2[12]) >> 1;
  3159.     dest[13] = (int) (source[13] + source2[13]) >> 1;
  3160.     dest[14] = (int) (source[14] + source2[14]) >> 1;
  3161.     dest[15] = (int) (source[15] + source2[15]) >> 1;
  3162.     dest += width;
  3163.     source += row_size;
  3164.     source2 += row_size;
  3165.       }
  3166.     }
  3167.   } else {            /* (width == 8) */
  3168.     assert(width == 8);
  3169.     if ((!right_half) && (!down_half)) {
  3170.       if (right & 0x1) {
  3171.     for (rr = 0; rr < width; rr++) {
  3172.       dest[0] = source[0];
  3173.       dest[1] = source[1];
  3174.       dest[2] = source[2];
  3175.       dest[3] = source[3];
  3176.       dest[4] = source[4];
  3177.       dest[5] = source[5];
  3178.       dest[6] = source[6];
  3179.       dest[7] = source[7];
  3180.       dest += 8;
  3181.       source += row_size;
  3182.     }
  3183.       } else if (right & 0x02) {
  3184.     short *d = (short *)dest;
  3185.     short *src = (short *)source;
  3186.     row_size >>= 1;
  3187.     for (rr = 0; rr < width; rr++) {
  3188.       d[0] = src[0];
  3189.       d[1] = src[1];
  3190.       d[2] = src[2];
  3191.       d[3] = src[3];
  3192.       d += 4;
  3193.       src += row_size;
  3194.     }
  3195.       } else {
  3196.     int *d = (int *)dest;
  3197.     int *src = (int *)source;
  3198.     row_size >>= 2;
  3199.     for (rr = 0; rr < width; rr++) {
  3200.       d[0] = src[0];
  3201.       d[1] = src[1];
  3202.       d += 2;
  3203.       src += row_size;
  3204.     }
  3205.       }
  3206.     } else {
  3207.       source2 = source + right_half + (row_size * down_half);
  3208.       for (rr = 0; rr < width; rr++) {
  3209.     dest[0] = (int) (source[0] + source2[0]) >> 1;
  3210.     dest[1] = (int) (source[1] + source2[1]) >> 1;
  3211.     dest[2] = (int) (source[2] + source2[2]) >> 1;
  3212.     dest[3] = (int) (source[3] + source2[3]) >> 1;
  3213.     dest[4] = (int) (source[4] + source2[4]) >> 1;
  3214.     dest[5] = (int) (source[5] + source2[5]) >> 1;
  3215.     dest[6] = (int) (source[6] + source2[6]) >> 1;
  3216.     dest[7] = (int) (source[7] + source2[7]) >> 1;
  3217.     dest += width;
  3218.     source += row_size;
  3219.     source2 += row_size;
  3220.       }
  3221.     }
  3222.   }
  3223. }
  3224.  
  3225.  
  3226.  
  3227. /*
  3228.  *--------------------------------------------------------------
  3229.  *
  3230.  * DoPictureDisplay --
  3231.  *
  3232.  *    Converts image from Lum, Cr, Cb to colormap space. Puts
  3233.  *      image in lum plane. Updates past and future frame
  3234.  *      pointers. Dithers image. Sends to display mechanism.
  3235.  *
  3236.  * Results:
  3237.  *    Pict image structure locked if displaying or if frame
  3238.  *      is needed as past or future reference.
  3239.  *
  3240.  * Side effects:
  3241.  *    Lum plane pummelled.
  3242.  *
  3243.  *--------------------------------------------------------------
  3244.  */
  3245.  
  3246. static void
  3247. DoPictureDisplay(vid_stream)
  3248.   VidStream *vid_stream;
  3249. {
  3250.  
  3251.   /* Update past and future references if needed. */
  3252.  
  3253.   if ((vid_stream->picture.code_type == I_TYPE) || (vid_stream->picture.code_type == P_TYPE)) {
  3254.     if (vid_stream->future == NULL) {
  3255.       vid_stream->future = vid_stream->current;
  3256.       vid_stream->future->locked |= FUTURE_LOCK;
  3257.     } else {
  3258.       if (vid_stream->past != NULL) {
  3259.     vid_stream->past->locked &= ~PAST_LOCK;
  3260.       }
  3261.       vid_stream->past = vid_stream->future;
  3262.       vid_stream->past->locked &= ~FUTURE_LOCK;
  3263.       vid_stream->past->locked |= PAST_LOCK;
  3264.       vid_stream->future = vid_stream->current;
  3265.       vid_stream->future->locked |= FUTURE_LOCK;
  3266.       vid_stream->current = vid_stream->past;
  3267.       ShowOutputVal(vid_stream); 
  3268.     }
  3269.   } else {
  3270.     ShowOutputVal(vid_stream); 
  3271.     }
  3272. }
  3273.  
  3274.  
  3275.  
  3276. /*
  3277.  *--------------------------------------------------------------
  3278.  *
  3279.  * ToggleBFlag --
  3280.  *
  3281.  *    Called to set no b frame processing flag.
  3282.  *
  3283.  * Results:
  3284.  *      No_B_Flag flag is toggled from present value to opposite value.
  3285.  *
  3286.  * Side effects:
  3287.  *      None.
  3288.  *
  3289.  *--------------------------------------------------------------
  3290.  */
  3291.  
  3292. void
  3293. ToggleBFlag()
  3294. {
  3295.   if (No_B_Flag) {
  3296.     No_B_Flag = 0;
  3297.   } else
  3298.     No_B_Flag = 1;
  3299. }
  3300.  
  3301.  
  3302.  
  3303.  
  3304. /*
  3305.  *--------------------------------------------------------------
  3306.  *
  3307.  * TogglePFlag --
  3308.  *
  3309.  *    Called to set no p frame processing flag.
  3310.  *
  3311.  * Results:
  3312.  *      No_P_Flag flag is toggled from present value to opposite value.
  3313.  *
  3314.  * Side effects:
  3315.  *      None.
  3316.  *
  3317.  *--------------------------------------------------------------
  3318.  */
  3319.  
  3320. void
  3321. TogglePFlag()
  3322. {
  3323.   if (No_P_Flag) {
  3324.     No_P_Flag = 0;
  3325.   } else
  3326.     No_P_Flag = 1;
  3327. }
  3328.